1

I have two service classes (there are more, of course, but those two are relevant here), which are in use during an integration test.

For test, I set up a mock (ConfigurationService) and stub two methods:

@ExtendWith(SpringExtension.class)
@ActiveProfiles("test")
@SpringBootTest
@TestPropertySource(properties =
        "spring.main.allow-bean-definition-overriding=true")
public class VehicleAuditExecutionServiceIT {

    @MockBean
    private ConfigurationService configurationServiceMock;

    @Autowired
    private VehicleAuditExecutionService vehicleAuditExecutionService;

    @Test
    void testExecuteVehicleAudits() throws IOException {

        // quite some DB operations for the test setup here

        AuditDurationConfigDTO auditDurationConfigDTO = new AuditDurationConfigDTO();

        auditDurationConfigDTO.setMaxDuration(deMaxDuration);
        Map<String, ScheduledAuditConfigDTO> map = new HashMap<>();
        map.put(country, ScheduledAuditConfigDTO.builder()
                .groupCalculationEnabled(false)
                .build());
        when(configurationServiceMock.getAuditDurationConfig(country)).thenReturn(auditDurationConfigDTO);
        when(configurationServiceMock.getScheduledAuditConfigurationForCountry(country)).thenReturn(ScheduledAuditConfigDTO.builder()
                        .groupCalculationEnabled(false)
                        .sameAuditDurationAllDealersSameGroupId(false)
                        .build());

        vehicleAuditExecutionService.executeVehicleAudits(startDate, country);

        verify(publishAuditInterfaceMock).pushExecutions(country, dealerDe1ExportAuditDtoList, auditCategory);
    }

    @ComponentScan(basePackages = "com.application")
    @SpringBootApplication
    @PropertySource("classpath:application-test.yml")
    static class TestConfiguration {}
}

After the setup, the stubbings are available:

Stubbings right before call to service

During the test's execution, vehicleAuditExecutionService.executeVehicleAudits(startDate, country) calls the AuditPreparationService, which in turn uses the configurationServiceMock (using @Autowired constructor injection). As expected, the calls gets matched and result set up is returned.

During the call, the stubbings are kept - everything works (Vol.1) During the call, the stubbings are kept - everything works (Vol.1)

Later, the execution returns to vehicleAuditExecutionService.executeVehicleAudits(startDate, country), where it calls the configurationServiceMock (@Autowired constructor injection, as well) again. But here, the mock's configuration has been changed: the mock's attribute mockitoInterceptor gets replaced by some other instance. Result: the stubbing is gone and the call returns null - leading to a NPE.

During the call - 3rd usage - attribute mockitoInterceptor changed

The screenshots were taken using org.springframework.boot:spring-boot-starter-parent:2.7.6, but I've tried that with multiple Spring Boot versions:

  • 2.7.0
  • 2.6.14
  • 2.5.14
  • 2.4.13
  • 2.3.12.RELEASE Each version has this issue - but I've never seen it in any other test. So I guess, there's something wrong with my test setup - but I cannot spot it.

Any idea, why this is happening?

Thanks a lot - please do not hesitate to ask for any further information, if needed for analysis.

kniffte

kniffte
  • 153
  • 1
  • 2
  • 7
  • if you want to use same bean for every test, check this solution : https://stackoverflow.com/a/69903960/2165146 – muhammed ozbilici Nov 26 '22 at 22:51
  • Thanks @muhammedozbilici. There is a distinct difference: the test linked talks about multiple Test running, using the same setup. But my problem comes during exactly one Test execution: Test ->Class1 calls Class2 (here, everything works) -> Class2 returns to Class1 -> Class1 tries to use the Mock (fails) -> ... -> End of Test – kniffte Nov 27 '22 at 09:54
  • that behave looks strange because those beans are singleton as default, must not change. – muhammed ozbilici Nov 27 '22 at 10:48

0 Answers0