How to make instance of CrudRepository interface during testing in Spring? How to make instance of CrudRepository interface during testing in Spring? xml xml

How to make instance of CrudRepository interface during testing in Spring?


This is what I have found is the minimal setup for a spring controller test which needs an autowired JPA repository configuration (using spring-boot 1.2 with embedded spring 4.1.4.RELEASE, DbUnit 2.4.8).

The test runs against a embedded HSQL DB which is auto-populated by an xml data file on test start.

The test class:

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

Notes:

  • @ContextConfiguration annotation which only includes the embedded TestController and the JPA configuration class RepoFactory4Test.

  • The @TestExecutionListeners annotation is needed in order that the subsequent annotations @DatabaseSetup and @DatabaseTearDown have effect

The referenced configuration class:

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

The UserRepository is a simple interface:

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

The EUser is a simple @Entity annotated class:

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

The FillTestData.xml:

<?xml version="1.0" encoding="UTF-8"?><dataset>    <user id="1"          email="alice@test.org"          ...    /></dataset>

The DbClean.xml:

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


If you're using Spring Boot, you can simplify these approaches a bit by adding @SpringBootTest to load in your ApplicationContext. This allows you to autowire in your spring-data repositories. Be sure to add @RunWith(SpringRunner.class) so the spring-specific annotations are picked up:

@RunWith(SpringRunner.class)@SpringBootTestpublic class OrphanManagementTest {  @Autowired  private UserRepository userRepository;  @Test  public void saveTest() {    User user = new User("Tom");    userRepository.save(user);    Assert.assertNotNull(userRepository.findOne("Tom"));  }}

You can read more about testing in spring boot in their docs.


You cant use repositories in your configuration class because from configuration classes it finds all its repositories using @EnableJpaRepositories.

  1. So change your Java Configuration to:
@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. If you have many repository implementation classes then create a separate class like below
@Servicepublic class RepositoryImpl {   @Autowired   private UserRepositoryImpl userService;}
  1. In your controller Autowire to RepositoryImpl and from there you can access all your repository implementation classes.
@AutowiredRepositoryImpl repository;

Usage:

repository.getUserService().findUserByUserName(userName);

Remove @Repository Annotation in ArticleRepository and ArticleServiceImpl should implement ArticleRepository not ArticleService.