java - 如何使用服务和存储库为 Spring Data 设置单元测试?

标签 java spring unit-testing

我已经检查了很多SO评论以及Spring数据和单元测试的文档,但我无法让它工作,我不知道为什么它不起作用。

我有一个 junit 测试类,如下所示:

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

    }

}

然后我的服务类看起来像这样

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

}

然后是我的存储库:

*/

public interface DealRepository extends CrudRepository<Deal, Long>{

    public List<Deal> getDealsBy_country(String country);

    public List<Deal> getAllDealsBy_employeeId(Long id);

}

我的配置文件如下所示:

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

但我收到此错误。

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)}

任何关于如何使用 spring data、junit 以及我的服务和存储库成功进行单元测试的建议将不胜感激。谢谢!

最佳答案

对于要注入(inject)的存储库 bean,

  • 您需要使用 spring-data 注释之一来启用存储库。因此,将 @Enable*Repositories 添加到您的配置类

  • 您还需要配置 dB 工厂和其他相关 bean。我正在使用 Mongo 并且配置了 mongoDbFactory bean

  • 在大多数情况下,您的测试配置应该类似于您的主配置,除了不必要的 bean 被模拟实现替换

更新 这是我的代码(抱歉我的代码在 mongo 中,我想你可以理解)

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

这是我的测试配置文件...正如您所看到的,它明确排除了我的主配置文件。

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

    @Autowired
    OrganizationService organizationService

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

那是我的测试课。它指的是测试配置,我建议使用命名配置类。您可以将常见选项放入父类(super class)中并扩展它们并将它们用于您的测试。

希望这有帮助

关于java - 如何使用服务和存储库为 Spring Data 设置单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41304135/

相关文章:

java - JTree有时不扩展

java - COMET/Server Push如何在Google app engine上实现?

java - 使用 JUnit 测试图像文件

java - 使用 spring 的 LDAP 主动通知

javascript - 摩卡和 Chai - "timeout of 2000ms exceeded. Ensure the done() callback is being called in this test."

Java 如何从另一个模拟方法调用一个方法

java - 根据另一个字符串的值确定一个字符串?

java - 初始作业没有接受任何资源;检查您的集群 UI 以确保工作人员已注册并拥有足够的资源

java - JUnit - 方法之前

java - 如何在执行时设置spring bootstrap.properties