it-swarm.com.de

Wie erstelle ich eine Instanz der CrudRepository-Schnittstelle während der Tests im Frühjahr?

Ich habe eine Spring-Anwendung und darin verwende ich nicht die XML-Konfiguration, nur Java Condfig. Alles ist in Ordnung, aber als ich versuchte, test es zu machen, hatte ich Probleme damit, ein Verdrahten der Komponenten in den Tests zu ermöglichen. Also fangen wir an, ich habe ein interface

@Repository
public interface ArticleRepository extends CrudRepository<Page, Long> {
    Article findByLink(String name);
    void delete(Page page);
}

Und eine Komponente/Dienstleistung

@Service
public class ArticleServiceImpl implements ArticleService {
    @Autowired
    private ArticleRepository articleRepository;
...
}

Ich möchte keine XML-Konfigurationen verwenden, daher versuche ich, ArticleServiceImpl für meine Tests nur mit Java Configuration zu testen. Also für den Testzweck habe ich gemacht:

@Configuration
@ComponentScan(basePackages = {"com.example.core", "com.example.repository"})
public class PagesTestConfiguration {


@Bean
public ArticleRepository articleRepository() {
       // (1) What to return ?
}

@Bean
public ArticleServiceImpl articleServiceImpl() {
    ArticleServiceImpl articleServiceImpl = new ArticleServiceImpl();
    articleServiceImpl.setArticleRepository(articleRepository());
    return articleServiceImpl;
}

}

In articleServiceImpl () muss ich eine Instanz von articleRepository () einfügen, aber es ist eine Schnittstelle. Wie erstelle ich ein neues Objekt mit einem neuen Schlüsselwort? Ist es möglich, ohne XML-Konfigurationsklasse zu erstellen und Autowiring zu aktivieren? Kann awtowired aktiviert werden, wenn beim Testen nur JavaConfigurations verwendet werden?

11
Xelian

Dies ist, was ich gefunden habe, die minimale Einrichtung für einen Federkontrollertest, für den eine automatische JPA-Repository-Konfiguration erforderlich ist (unter Verwendung des Federstiefels 1.2 mit eingebetteter Feder 4.1.4.RELEASE, DbUnit 2.4.8). 

Der Test wird mit einer eingebetteten HSQL-Datenbank ausgeführt, die beim Teststart von einer XML-Datendatei automatisch aufgefüllt wird.

Die Testklasse:

@RunWith( SpringJUnit4ClassRunner.class )
@ContextConfiguration( classes = { TestController.class,
                                   RepoFactory4Test.class } )
@TestExecutionListeners( { DependencyInjectionTestExecutionListener.class,
                           DirtiesContextTestExecutionListener.class,
                           TransactionDbUnitTestExecutionListener.class } )
@DatabaseSetup( "classpath:FillTestData.xml" )
@DatabaseTearDown( "classpath:DbClean.xml" )
public class ControllerWithRepositoryTest
{
    @Autowired
    private TestController myClassUnderTest;

    @Test
    public void test()
    {
        Iterable<EUser> list = myClassUnderTest.findAll();

        if ( list == null || !list.iterator().hasNext() )
        {
            Assert.fail( "No users found" );
        }
        else
        {
            for ( EUser eUser : list )
            {
                System.out.println( "Found user: " + eUser );
            }
        }
    }

    @Component
    static class TestController
    {
        @Autowired
        private UserRepository myUserRepo;

        /**
         * @return
         */
        public Iterable<EUser> findAll()
        {
            return myUserRepo.findAll();
        }
    }
}

Anmerkungen: 

  • @ContextConfiguration-Annotation, die nur den eingebetteten TestController und die JPA-Konfigurationsklasse RepoFactory4Test enthält.

  • Die Annotation @TestExecutionListeners ist erforderlich, damit die nachfolgenden Annotationen @DatabaseSetup und @DatabaseTearDown wirksam werden

Die referenzierte Konfigurationsklasse:

@Configuration
@EnableJpaRepositories( basePackageClasses = UserRepository.class )
public class RepoFactory4Test
{
    @Bean
    public DataSource dataSource()
    {
        EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
        return builder.setType( EmbeddedDatabaseType.HSQL ).build();
    }

    @Bean
    public EntityManagerFactory entityManagerFactory()
    {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setGenerateDdl( true );

        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setJpaVendorAdapter( vendorAdapter );
        factory.setPackagesToScan( EUser.class.getPackage().getName() );
        factory.setDataSource( dataSource() );
        factory.afterPropertiesSet();

        return factory.getObject();
    }

    @Bean
    public PlatformTransactionManager transactionManager()
    {
        JpaTransactionManager txManager = new JpaTransactionManager();
        txManager.setEntityManagerFactory( entityManagerFactory() );
        return txManager;
    }
}

Das UserRepository ist eine einfache Schnittstelle:

public interface UserRepository extends CrudRepository<EUser, Long>
{
}   

Der EUser ist eine einfache, mit @Entity versehene Klasse:

@Entity
@Table(name = "user")
public class EUser
{
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Max( value=Integer.MAX_VALUE )
    private Long myId;

    @Column(name = "email")
    @Size(max=64)
    @NotNull
    private String myEmail;

    ...
}

Die FillTestData.xml:

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
    <user id="1"
          email="[email protected]"
          ...
    />
</dataset>

Die DbClean.xml:

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
    <user />
</dataset>
11
Heri

Wenn Sie Spring Boot verwenden, können Sie diese Ansätze ein wenig vereinfachen, indem Sie @SpringBootTest hinzufügen, um sie in Ihre ApplicationContext zu laden. Auf diese Weise können Sie Ihre Quelldaten-Repositories automatisch abwickeln. Stellen Sie sicher, dass Sie @RunWith(SpringRunner.class) hinzufügen, damit die frühlingsspezifischen Anmerkungen aufgenommen werden:

@RunWith(SpringRunner.class)
@SpringBootTest
public class OrphanManagementTest {

  @Autowired
  private UserRepository userRepository;

  @Test
  public void saveTest() {
    User user = new User("Tom");
    userRepository.save(user);
    Assert.assertNotNull(userRepository.findOne("Tom"));
  }
}

Weitere Informationen zum Testen von Spring Boot finden Sie in docs .

6
heez

Sie können keine Repositorys in Ihrer Konfigurationsklasse verwenden, da von den Konfigurationsklassen aus alle @ Repositorys mit @EnableJpaRepositories gefunden werden.

  1. Ändern Sie also Ihre Java-Konfiguration in:
@Configuration
@EnableWebMvc
@EnableTransactionManagement
@ComponentScan("com.example")
@EnableJpaRepositories(basePackages={"com.example.jpa.repositories"})//Path of your CRUD repositories package
@PropertySource("classpath:application.properties")
public class JPAConfiguration {
  //Includes jpaProperties(), jpaVendorAdapter(), transactionManager(), entityManagerFactory(), localContainerEntityManagerFactoryBean()
  //and dataSource()  
}
  1. Wenn Sie über viele Repository-Implementierungsklassen verfügen, erstellen Sie eine separate Klasse (siehe unten)
@Service
public class RepositoryImpl {
   @Autowired
   private UserRepositoryImpl userService;
}
  1. In Ihrem Controller Autowire zu RepositoryImpl und von dort aus können Sie auf alle Repository-Implementierungsklassen zugreifen.
@Autowired
RepositoryImpl repository;

Verwendungszweck:

repository.getUserService (). findUserByUserName (Benutzername);

Entfernen Sie @Repository-Annotation in ArticleRepository und ArticleServiceImpl sollte ArticleRepository und nicht ArticleService implementieren.

1
sagar

Was Sie tun müssen, ist:

  1. @Repository aus ArticleRepository entfernen

  2. @EnableJpaRepositories zu PagesTestConfiguration.Java hinzufügen

    @Configuration
    @ComponentScan(basePackages = {"com.example.core"}) // are you sure you wanna scan all the packages?
    @EnableJapRepository(basePackageClasses = ArticleRepository.class) // assuming you have all the spring data repo in the same package.
    public class PagesTestConfiguration {
    
    @Bean
    public ArticleServiceImpl articleServiceImpl() {
        ArticleServiceImpl articleServiceImpl = new ArticleServiceImpl();
        return articleServiceImpl;
    }
    }
    
0
Jaiwo99