web-dev-qa-db-fra.com

Comment créer une instance de l'interface CrudRepository lors des tests au printemps?

J'ai une application Spring dans laquelle je _ {ne pas utilise la configuration xml, uniquement Java Condfig. Tout va bien, mais lorsque j'essaie de test cela, je rencontrais des problèmes pour activer le câblage des composants dans les tests. Commençons donc j'ai un interface

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

Et un composant/service

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

Je ne veux pas utiliser les configurations xml, donc pour mes tests, j'essaie de tester ArticleServiceImpl en utilisant uniquement la configuration Java. Donc, dans le but de tester, j'ai fait:

@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;
}

}

Dans articleServiceImpl _ (), je dois mettre une instance de articleRepository_ () mais c'est une interface. Comment créer un nouvel objet avec un nouveau mot clé? Est-il possible sans créer la classe de configuration XML et activer le transfert automatique? Peut-on activer awtowired lorsqu’on utilise uniquement JavaConfigurations lors des tests?

11
Xelian

C’est ce que j’ai trouvé, c’est la configuration minimale d’un test de contrôleur de ressort nécessitant une configuration de référentiel JPA auto-câblé (avec spring-boot 1.2 avec un ressort intégré 4.1.4.RELEASE, DbUnit 2.4.8). 

Le test s'exécute sur une base de données HSQL intégrée, qui est automatiquement renseignée par un fichier de données xml au début du test.

La classe de test:

@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();
        }
    }
}

Remarques: 

  • Annotation @ContextConfiguration qui inclut uniquement TestController intégré et la classe de configuration JPA RepoFactory4Test.

  • L'annotation @TestExecutionListeners est nécessaire pour que les annotations suivantes @DatabaseSetup et @DatabaseTearDown aient un effet.

La classe de configuration référencée:

@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;
    }
}

UserRepository est une interface simple:

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

EUser est une simple classe annotée @Entity:

@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;

    ...
}

Le FillTestData.xml:

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

Le fichier DbClean.xml:

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

Si vous utilisez Spring Boot, vous pouvez simplifier un peu ces approches en ajoutant @SpringBootTest à charger dans votre ApplicationContext. Cela vous permet de connecter automatiquement vos référentiels de données de printemps. Assurez-vous d'ajouter @RunWith(SpringRunner.class) pour que les annotations spécifiques au printemps soient relevées:

@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"));
  }
}

Vous pouvez en savoir plus sur les tests dans Spring Boot dans leurs docs .

6
heez

Vous ne pouvez pas utiliser de référentiels dans votre classe de configuration car, à partir des classes de configuration, il trouve tous ses référentiels à l'aide de @EnableJpaRepositories.

  1. Alors changez votre configuration Java pour:
@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. Si vous avez plusieurs classes d'implémentation de référentiel, créez une classe séparée comme ci-dessous.
@Service
public class RepositoryImpl {
   @Autowired
   private UserRepositoryImpl userService;
}
  1. Dans votre contrôleur, Autowire to RepositoryImpl et à partir de là, vous pouvez accéder à toutes vos classes d'implémentation de référentiel.
@Autowired
RepositoryImpl repository;

Usage:

repository.getUserService (). findUserByUserName (userName);

Supprimez @Repository Annotation dans ArticleRepository et ArticleServiceImpl doit implémenter ArticleRepository et non ArticleService.

1
sagar

Ce que vous devez faire c'est:

  1. supprimer @Repository de ArticleRepository

  2. ajouter @EnableJpaRepositories à PagesTestConfiguration.Java

    @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