Spring 单元测试 JPA 存储库

Posted

技术标签:

【中文标题】Spring 单元测试 JPA 存储库【英文标题】:Spring Unit test JPA repository 【发布时间】:2014-08-13 14:54:27 【问题描述】:

我是 Spring 框架的新手。我需要为 JPA 存储库编写单元测试。我正在尝试简单的存储库saveAndFlush() 方法。但是我的存储库中没有任何内容。这是我的源代码:

TestContext.class

@Configuration 
@PropertySource("classpath:log4j.properties") 
public class TestContext 

    @Bean
    public RoleService roleService() 
        return Mockito.mock(RoleService.class);
    

    @Bean
    public RightService RightService() 
        return Mockito.mock(RightService.class);
    

    @Bean
    public RoleRepository RoleRepository() 
        return Mockito.mock(RoleRepository.class); 
    

RoleServiceTest.class

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestContext.class)
@WebAppConfiguration
public class RoleServiceTest 

    @Autowired
    private RoleRepository roleRepository;

    @Test
    public void TestServices() throws Exception 
        RoleDetails first = new RoleDetails();
        first.setId("1");
        first.setDescription("First Description");
        first.setName("First");
        roleRepository.saveAndFlush(new RoleEntity(first));
        roleRepository.save(new RoleEntity(first));
        List<RoleEntity> roles = new ArrayList<RoleEntity>();
        roles = roleRepository.findAll();
        System.out.println(roles);
        assertEquals(1, roles.size());
    

还有错误:

java.lang.AssertionError: expected:<1> but was:<0>

我几乎可以肯定问题是由于 testContext.Class 而发生的。我使用这个类来测试我的控制器,它运行良好,但现在我需要测试我的数据库,我不知道如何修改 contextConfiguration。我希望有人能帮助我。提前致谢!

【问题讨论】:

【参考方案1】:

问题确实来自 TestContext。您尝试使用模拟对象保存对象,这是不正确的。

解决方案是使用真实的存储库。为此,您需要执行以下步骤:

    使用 @Repository 注释注释您的 RoleRepository 并使用 JpaRepository(RoleEntity,ID) 扩展类(其中 ID 是您声明 RoleEntity id 的类型) . 将 RoleRepository 添加到您的上下文配置类(真正的,而不是测试的)。您可以通过添加 @EnableJpaRepositories(value="your.repository.package") 来做到这一点。 将 RoleServiceTest 类上 @ContextConfiguration 注释中的 TestContext.class 替换为您用于配置基于 Spring 的项目的真实上下文配置类。

希望我的回答对你有帮助,如果您还需要帮助,请随时再次提问!

【讨论】:

真实的在哪里,测试的上下文配置类在哪里?【参考方案2】:

您的存储库是一个模拟对象。根据定义,模拟对象是一个不做它通常应该做的事情,而是做你在测试中告诉它做的事情的对象。

要测试存储库,存储库必须是真实的。因此,您的上下文类应该有

@Bean
public RoleRepository RoleRepository() 
    return new RoleRepositoryImpl(); // or whatever the class implementing the repository is 

【讨论】:

这在技术上是正确的,但是很多 Spring 数据存储库使用自动实现逻辑来进行基本的 CRUD 操作。试图直接实例化它们是行不通的;你应该展示如何使用@Autowired@Resource 来获取它们。【参考方案3】:

如果使用 Spring Boot,创建​​一个 Web 应用程序并且您正在运行 Application.class 中的 main() 方法,您可以使用:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
public class MyUnitTest 

    Some someInstance = new Some();

    @Autowired
    private SomeRepository someRepository;


@Test
public void testSomeClass() throws Exception 
    Some savedSome = someRepository.save(someInstance);
    assertEquals(1, someRepository.count());

【讨论】:

这实际上是一个集成测试而不是单元测试,对吧?用于单元测试的 mockito 运行器,用于集成的 springjunit 运行器

以上是关于Spring 单元测试 JPA 存储库的主要内容,如果未能解决你的问题,请参考以下文章

对 Spring Data JPA @Query 进行单元测试是不可能的,真的吗?

Spring Boot中JPA Repository的Save方法的单元测试

Spring JPA Junit 关闭自动回滚

Spring Boot:在单元测试中用一个覆盖多个bean

spring 声明式事务管理在真实的Service和单元测试时的回滚情况,需要注意的问题,jpa为例子

Spring Boot - DI - 单元测试