简体   繁体   中英

How to set up a unit test for spring data with service and repository?

I have checked many SO comments and the docs for spring data and unit testing but I cant get this to work and I dont know why its not working.

I have a junit test class that looks like this:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class DealServiceTest {

    @Configuration
    static class ContextConfiguration {

        // this bean will be injected into the OrderServiceTest class
        @Bean
        public DealService orderService() {
            DealService dealService = new DealService();
            // set properties, etc.
            return dealService;
        }

        @Bean
        public EmployeeService employeeService(){
            EmployeeService employeeService = new EmployeeService();
            return employeeService;
        }

    }

    @Autowired
    DealService dealService;

    @Autowired
    EmployeeService employeeService;

    @Test
    public void createDeal() throws ServiceException {
        Employee employee = new Employee("Daniel", "tuttle", "danielptm@me.com", "dannyboy", "secret password", 23.234, 23.23);
        Deal d = dealService.createDeal("ADSF/ADSF/cat.jpg", "A title goes here", "A deal description", 23.22, "Name of business", 23.23,23.23, employee, "USA" );
        Assert.assertNotNull(d);

    }

}

And then I have my service class that looks like this

@Service
public class DealService {

    @Autowired
    private DealRepository dealRepository;

    public Deal createDeal(String image, String title, String description, double distance, String location, double targetLat, double targetLong, Employee employee, String country) throws ServiceException {
        Deal deal = new Deal(image, title, description, distance, location, targetLat, targetLong, employee, country);
        try {
            return dealRepository.save(deal);
        }catch(Exception e){
            throw new ServiceException("Could not create a deal: "+deal.toString(), e);
        }
    }

    public Deal updateDeal(Deal d) throws ServiceException {
        try{
            return dealRepository.save(d);
        }catch(Exception e){
            throw new ServiceException("Could not update deal at this time: "+d.toString(),e);
        }
    }

    public List<Deal> getAllDealsForEmployeeId(Employee employee) throws ServiceException {
        try{
            return dealRepository.getAllDealsBy_employeeId(employee.getId());
        }catch(Exception e){
            throw new ServiceException("Could not get deals for employee: "+employee.getId(), e);
        }
    }

}

And then my repository:

*/

public interface DealRepository extends CrudRepository<Deal, Long>{

    public List<Deal> getDealsBy_country(String country);

    public List<Deal> getAllDealsBy_employeeId(Long id);

}

My config file looks like this:

@Configuration
@EnableJpaRepositories("com.globati.repository")
@EnableTransactionManagement
public class InfrastructureConfig {

    @Bean
    public DataSource dataSource() {
        HikariConfig config = new HikariConfig();
        config.setDriverClassName("com.mysql.jdbc.Driver");
        config.setJdbcUrl("jdbc:mysql://localhost:3306/DatabaseProject");
        config.setUsername("awesome");
        config.setPassword("database");
        return new HikariDataSource(config);
    }

//  @Bean
//  public DataSource derbyDataSource(){
//      HikariConfig config = new HikariConfig();
//      config.setDriverClassName("jdbc:derby:memory:dataSource");
//      config.setJdbcUrl("jdbc:derby://localhost:1527/myDB;create=true");
//      config.setUsername("awesome");
//      config.setPassword("database");
//
//      return new HikariDataSource(config);
//
//  }

    @Bean
    public JpaTransactionManager transactionManager(EntityManagerFactory factory) {
        return new JpaTransactionManager(factory);
    }

    @Bean
    public JpaVendorAdapter jpaVendorAdapter() {

        HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        adapter.setDatabase(Database.MYSQL);
        adapter.setGenerateDdl(true);

        return adapter;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {

        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setDataSource(dataSource()); //Get data source config here!
        factory.setJpaVendorAdapter(jpaVendorAdapter());
        factory.setPackagesToScan("com.globati.model");

        return factory;
    }
}

But I get this error.

java.lang.IllegalStateException: Failed to load ApplicationContext ...

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean found for dependency [com.globati.repository.DealRepository]: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Any suggestions for how I can successfully do unit testing with spring data, junit and with my service and repositories would be greatly appreciated. Thanks!

For a repository bean to be injected,

  • You need to enable Repositories, using one of the spring-data annotations. So add @Enable*Repositories to your configuration class

  • You also need dB factories and other related beans configured. I am using Mongo and I have mongoDbFactory bean configured

  • And for the most part your test configuration should look like your main configuration except for unnecessary bean replaced by mock implementations

UPDATE Here is my code (sorry mine is in mongo, I think you can relate)

@Configuration
@WebAppConfiguration
@ComponentScan(basePackages = "com.amanu.csa",
        excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = WebConfig.class))
@EnableMongoRepositories(repositoryImplementationPostfix = "CustomImpl")
class TestConfig {

    @Bean
    Mongo mongo() throws Exception {
        return new MongoClient("localhost")
    }

    @Bean
    MongoDbFactory mongoDbFactory() throws Exception {
        return new SimpleMongoDbFactory(mongo(), "csa_test")
    }

    @Bean
    MongoTemplate mongoTemplate() throws Exception {
        MongoTemplate template = new MongoTemplate(mongoDbFactory())
        template.setWriteResultChecking(WriteResultChecking.EXCEPTION)
        return template
    }
}

That is my test config file... As you can see it explicitly excludes my main configuration file.

@ContextConfiguration(classes = TestConfig)
@RunWith(SpringRunner.class)
class OrganizationServiceTest {

    @Autowired
    OrganizationService organizationService

     @Test
    void testRegister() {
        def org = new Organization()
        //...
        organizationService.register(org)
        // ...
    }

And that is my test class. It refers to the test config, and I recommend using named config classes. You can put common options onto a super class and extend those and use them for your tests.

I hope this helps

You can try to add

@ActiveProfiles("your spring profile") 

In addition I would suggest to use an embedded test db like flapdoodle ( https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo )

You could either :

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM