无法使用Mockito

时间:2016-06-06 11:11:03

标签: spring-boot mockito spring-data-jpa

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

我使用Spring Boot和Spring Data JPA来构建应用程序。 Mockito用于嘲笑。我设法将问题提炼成一个测试项目。完整的测试项目位于GitHub。以下是测试项目的代码片段;以下是PersonServiceTest类。

更新1: before()代码应检查personRepository而不是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-beanmock-person-repository。基本上,我使用配置文件来确定应该嘲笑什么。在进行任何测试之前,我断言someBeanpersonService是模拟实例。 someBean被正确嘲笑,但personService总是失败。以下代码是TestConfig类的代码。

@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:仍在寻找理想的解决方案

我仍然很感激解决方案。虽然我已经将解决​​方案标记为已接受,但建议的解决方案并不理想。因为存在不同级别的集成测试(从端到端测试到具有少量依赖性的非常窄的测试范围)。

1 个答案:

答案 0 :(得分:4)

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

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

你不是在嘲笑PersonService因此有理由认为它会使这个断言失败。

另一个问题是Spring Data JPA还将创建一个名为personRepository的bean。因此,除非您更改其名称,否则将忽略您的模拟存储库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);
}

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

无论如何,更清洁的解决方案是使用MockitoJUnitRunner代替Springs测试跑步者。您需要做的就是使用@InjectMocks注释要测试的类以及要模拟并注入@Mock的所有依赖项:像这样:

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

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