无法使用 Mockito 模拟 Spring-Data-JPA 存储库

2024-05-08

我正在尝试为服务编写测试。但我没有成功地嘲笑repository依赖性。其他非存储库依赖项已成功模拟。存储库实例始终是实际实现,而不是模拟实例。

我正在使用 Spring Boot 和 Spring Data JPA 来构建应用程序。 Mockito 用于模拟。我设法将问题提炼到一个测试项目中。完整的测试项目已上线GitHub https://github.com/ChrisZhong/spring-boot-data-jpa-mockito-testing。以下是测试项目的代码片段;以下是PersonServiceTest class.

更新1: before()应该检查代码personRepository not personService

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(App.class)
@WebAppConfiguration
@TestExecutionListeners({ServletTestExecutionListener.class, DirtiesContextBeforeModesTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class, TransactionalTestExecutionListener.class, SqlScriptsTestExecutionListener.class})
@Transactional
@ActiveProfiles({"mock-some-bean", "mock-person-repository"})
public class PersonServiceTest {

    @Inject
    private SomeBean someBean;
    @Inject
    private PersonRepository personRepository;
    @Inject
    private PersonService personService;

    @Before
    public void before() {
        assertThat(mockingDetails(someBean).isMock(), is(true));
        assertThat(mockingDetails(personRepository).isMock(), is(true));
    }

    @Test
    public void doSomething() throws Exception { ... }
}

测试类使用两个配置文件:mock-some-bean and mock-person-repository。基本上,我使用配置文件来确定应该嘲笑什么。在进行任何测试之前,我断言someBean and personService是模拟实例。someBean被正确地嘲笑但是personService总是失败。下面的代码是来自TestConfig class.

@Configuration
public class TestConfig {

    private static final Logger logger = LoggerFactory.getLogger(TestConfig.class);

    @Bean
    @Profile("mock-some-bean")
    public SomeBean someBean() {
        logger.info("Mocking: {}", SomeBean.class);
        return mock(SomeBean.class);
    }

    @Bean
    @Profile("mock-person-repository")
    public PersonRepository personRepository() {
        logger.info("Mocking: {}", PersonRepository.class);
        return mock(PersonRepository.class);
    }
}

更新2:问题更清楚了

我缺少什么?看来 Spring Data JPA 总是创建一个实例并忽略@Bean定义在TestConfig班级。如何“告诉”Spring Data JPA 不要创建实例?我很感谢我能得到的任何帮助来解决这个问题。

更新3:仍在寻找理想的解决方案

我仍然希望有一个解决方案。尽管我已将解决方案标记为已接受,但建议的解决方案并不理想。因为存在不同级别的集成测试(从端到端测试到具有一小组依赖项的非常窄范围的测试)。


这里有几个问题。我假设您正在尝试验证是否PersonRepository是否被嘲笑。但是,在您的测试中您写道:

assertThat(mockingDetails(personService).isMock(), is(true));

你不是在嘲笑PersonService所以这个断言失败是有道理的。


另一个问题是 Spring Data JPA 还将创建一个名为的 beanpersonRepository。因此,除非您更改其名称,否则您的模拟存储库 bean 将被忽略:

@Bean
@Profile("mock-person-repository")
// Change method name to change bean name
public PersonRepository personRepositoryMock() {
    logger.info("Mocking: {}", PersonRepository.class);
    return mock(PersonRepository.class);
}

但如果你这样做,那么将会有两个类型的 beanPersonRepository,因此将其自动装配到您的服务中将会失败。要解决这个问题,您必须阻止它使用 Spring Data JPA 创建存储库。


无论如何,一个更干净的解决方案是使用MockitoJUnitRunner而不是 Springs 测试运行程序。您所要做的就是注释您想要测试的类@InjectMocks以及您想要模拟和注入的所有依赖项@Mock: 像这样:

@InjectMocks
private PersonService personService;
@Mock
private SomeBean someBean;
@Mock
private PersonRepository repository;

然后就可以删除了TestConfig并删除测试中的所有注释并将其替换为@RunWith(MockitoJUnitRunner.class).

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无法使用 Mockito 模拟 Spring-Data-JPA 存储库 的相关文章

随机推荐