ness
ness

Reputation: 11

Integration tests sometimes throw "java.lang.IllegalStateException: Data source context must be initialized"

It seems to happen randomly when running integration tests that need docker. Happens only on Windows.

stack trace:

java.lang.IllegalStateException: Data source context must be initialized
    at io.zonky.test.db.shaded.com.google.common.base.Preconditions.checkState(Preconditions.java:459) ~[embedded-database-spring-test-2.1.1.jar:na]
    at io.zonky.test.db.context.DefaultDatabaseContext.reset(DefaultDatabaseContext.java:190) ~[embedded-database-spring-test-2.1.1.jar:na]
    at io.zonky.test.db.EmbeddedDatabaseTestExecutionListener.lambda$resetDatabases$0(EmbeddedDatabaseTestExecutionListener.java:59) ~[embedded-database-spring-test-2.1.1.jar:na]
    at io.zonky.test.db.EmbeddedDatabaseTestExecutionListener.lambda$forEachDatabase$5(EmbeddedDatabaseTestExecutionListener.java:98) ~[embedded-database-spring-test-2.1.1.jar:na]
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) ~[na:na]
    at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177) ~[na:na]
    at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177) ~[na:na]
    at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133) ~[na:na]
    at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801) ~[na:na]
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[na:na]
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[na:na]
    at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) ~[na:na]
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) ~[na:na]
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
    at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497) ~[na:na]
    at io.zonky.test.db.EmbeddedDatabaseTestExecutionListener.forEachDatabase(EmbeddedDatabaseTestExecutionListener.java:96) ~[embedded-database-spring-test-2.1.1.jar:na]
    at io.zonky.test.db.EmbeddedDatabaseTestExecutionListener.resetDatabases(EmbeddedDatabaseTestExecutionListener.java:58) ~[embedded-database-spring-test-2.1.1.jar:na]
    at io.zonky.test.db.EmbeddedDatabaseTestExecutionListener.beforeTestClass(EmbeddedDatabaseTestExecutionListener.java:34) ~[embedded-database-spring-test-2.1.1.jar:na]
    at org.springframework.test.context.TestContextManager.beforeTestClass(TestContextManager.java:213) ~[spring-test-5.3.14.jar:5.3.14]
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:60) ~[spring-test-5.3.14.jar:5.3.14]
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) ~[spring-test-5.3.14.jar:5.3.14]
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) ~[junit-4.13.1.jar:4.13.1]
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413) ~[junit-4.13.1.jar:4.13.1]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190) ~[spring-test-5.3.14.jar:5.3.14]
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137) ~[junit-4.13.1.jar:4.13.1]
    at org.junit.runner.JUnitCore.run(JUnitCore.java:115) ~[junit-4.13.1.jar:4.13.1]
    at org.junit.vintage.engine.execution.RunnerExecutor.execute(RunnerExecutor.java:43) ~[junit-vintage-engine-5.7.2.jar:5.7.2]
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) ~[na:na]
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) ~[na:na]
    at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133) ~[na:na]
    at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801) ~[na:na]
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[na:na]
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[na:na]
    at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) ~[na:na]
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) ~[na:na]
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
    at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497) ~[na:na]
    at org.junit.vintage.engine.VintageTestEngine.executeAllChildren(VintageTestEngine.java:82) ~[junit-vintage-engine-5.7.2.jar:5.7.2]
    at org.junit.vintage.engine.VintageTestEngine.execute(VintageTestEngine.java:73) ~[junit-vintage-engine-5.7.2.jar:5.7.2]
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108) ~[junit-platform-launcher-1.7.2.jar:1.7.2]
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88) ~[junit-platform-launcher-1.7.2.jar:1.7.2]
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54) ~[junit-platform-launcher-1.7.2.jar:1.7.2]
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67) ~[junit-platform-launcher-1.7.2.jar:1.7.2]
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52) ~[junit-platform-launcher-1.7.2.jar:1.7.2]
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96) ~[junit-platform-launcher-1.7.2.jar:1.7.2]
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75) ~[junit-platform-launcher-1.7.2.jar:1.7.2]
    at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57) ~[junit5-rt.jar:na]
    at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38) ~[junit-rt.jar:na]
    at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11) ~[idea_rt.jar:na]
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35) ~[junit-rt.jar:na]
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235) ~[junit-rt.jar:na]
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54) ~[junit-rt.jar:na]


Test ignored.

integration test class which fails:

@RunWith(SpringRunner.class)
@SpringBootTest()
@Import({FirebaseServerMock.class})
@AutoConfigureMockMvc
@AutoConfigureEmbeddedDatabase
@ComponentScan(excludeFilters = {
    @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = FirebaseConnectorService.class),
    @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = UserEntity.class),
})
@TestPropertySource(properties = {
    "scheduler.defaultMinimumPreOrderTime=-999990",
    "scheduler.vehicleCheckDurationMinutes=15",
    "scheduler.immutability.minutesBeforeTripDeparture=2000", // more than 24h
    "scheduler.breakSchedulingMarginMinutes=10"
})
public class PicturesUploadForDriverIntegrationTest {

    @Autowired
    MockMvc mockMvc;

    @Autowired
    FirebaseServerMock firebaseServerMock;

    @Autowired
    UserRepository userRepository;

    @Autowired
    DriverRepository driverRepository;

    @Autowired
    FileRepository fileRepository;

    @Autowired
    DriverFileRepository driverFileRepository;

    @Autowired
    ScheduledFileTasks scheduledFileTasks;

    @Value("classpath:other/id_card_1.jpg")
    private Resource file1;

    @Value("classpath:other/id_card_2.jpg")
    private Resource file2;

    final UUID DRIVER = UUID.fromString("d333d333-ea5f-4d89-8d72-e6eb63bb3b83"); // from sql
    final UUID DRIVER_USER = UUID.fromString("d444d444-ea5f-4d89-8d72-e6eb63bb3b84"); // from sql
    final UUID DISTRIBUTOR_USER = UUID.fromString("d444d444-ea5f-4d89-8d72-e6eb63bb3b83"); // from sql

    MockMultipartFile fileMock1, fileMock2;

    @Test
    @Sql("/fixtures/picturesUploadForDriver.sql")
    @FlywayTest
    @Transactional
    public void uploadPicturesTest() throws Exception {
        // prepare object mapper
        AccessToken driverToken = firebaseServerMock.mockVerifiableToken(userRepository.findByUuid(DRIVER_USER).orElse(null).getFirebaseUid());
        AccessToken distributorToken = firebaseServerMock.mockVerifiableToken(userRepository.findByUuid(DISTRIBUTOR_USER).orElse(null).getFirebaseUid());

        /*
         * 1) as driver, I open the driver app (whoAmI context is asked) and I become information, that I need upload driver licence pictures
         */
        MvcResult resultDriverWhoAmI1 = mockMvc.perform(
                get("/api/whoami")
                    .header("Authorization", "Bearer " + driverToken.getValue())
            )
            .andExpect(status().isOk())
            .andReturn();

        String whoAmI1Json = resultDriverWhoAmI1.getResponse().getContentAsString();
        assertThat(whoAmI1Json, hasJsonPath("$.isDriverLicenceCheckNeeded", equalTo(true))); // file(s) upload must be done
        assertThat(whoAmI1Json, hasJsonPath("$.userId", equalTo(DRIVER_USER.toString())));
        assertThat(whoAmI1Json, hasJsonPath("$.email", equalTo("[email protected]")));
        assertThat(whoAmI1Json, hasJsonPath("$.name", equalTo("Patra, Cleo")));
        assertThat(whoAmI1Json, hasJsonPath("$.phone", equalTo("0987654321")));
        assertThat(whoAmI1Json, hasJsonPath("$.dateOfBirth", equalTo(null)));
        assertThat(whoAmI1Json, hasJsonPath("$.address.streetNumber", equalTo(null)));
        assertThat(whoAmI1Json, hasJsonPath("$.address.zipCode", equalTo(null)));
        assertThat(whoAmI1Json, hasJsonPath("$.address.city", equalTo(null)));
        assertThat(whoAmI1Json, hasJsonPath("$.address.country", equalTo(null)));
        assertThat(whoAmI1Json, hasJsonPath("$.pleaseComplete", equalTo(false)));
        assertThat(whoAmI1Json, hasJsonPath("$.isStripeCustomerConnected", equalTo(false)));
        assertThat(whoAmI1Json, hasJsonPath("$.hasDefaultStripePaymentMethod", equalTo(false)));
        assertThat(whoAmI1Json, hasJsonPath("$.privileges.[*]", hasSize(11)));

        /*
         * 2) as driver, I use the driver app to upload 2 files
         */
        // prepare file mocks
        fileMock1 = new MockMultipartFile(
            "file",
            "id_card_1.jpg",
            MediaType.IMAGE_JPEG_VALUE,
            file1.getInputStream()
        );
        fileMock2 = new MockMultipartFile(
            "file",
            "id_card_2.jpg",
            MediaType.IMAGE_JPEG_VALUE,
            file2.getInputStream()
        );
        MvcResult resultDriverFile1Upload = mockMvc.perform(
                multipart("/api/files/driver-licence/upload")
                    .file(fileMock1)
                    .header("Authorization", "Bearer " + driverToken.getValue())
            )
            .andExpect(status().isOk())
            .andReturn();

        String resultDriverFile1Json = resultDriverFile1Upload.getResponse().getContentAsString();
        assertThat(resultDriverFile1Json, hasJsonPath("$.name", equalTo("id_card_1.jpg")));
        String fileId1 = JsonPath.read(resultDriverFile1Json, "$.fileId");

        MvcResult resultDriverFile2Upload = mockMvc.perform(
                multipart("/api/files/driver-licence/upload")
                    .file(fileMock2)
                    .header("Authorization", "Bearer " + driverToken.getValue())
            )
            .andExpect(status().isOk())
            .andReturn();

        String resultDriverFile2Json = resultDriverFile2Upload.getResponse().getContentAsString();
        assertThat(resultDriverFile2Json, hasJsonPath("$.name", equalTo("id_card_2.jpg")));
        String fileId2 = JsonPath.read(resultDriverFile2Json, "$.fileId");

        // check, whether files saved in db
        assertTrue(fileRepository.findByUuid(UUID.fromString(fileId1)).isPresent());
        assertTrue(fileRepository.findByUuid(UUID.fromString(fileId2)).isPresent());

        /*
         * 3) as driver, I use the driver app to assign uploaded files to me
         */
        String sendFilesBody = "{\n" +
            "\"fileIds\": [\"" + fileId1 + "\",\"" + fileId2 + "\"],\n" +
            "\"fileType\": \"DRIVER_LICENSE\"\n" +
            "}";
        mockMvc.perform(
                post("/api/command/saveDriverFiles")
                    .content(sendFilesBody)
                    .contentType(MediaType.APPLICATION_JSON)
                    .header("Authorization", "Bearer " + driverToken.getValue())
            );

        // check driver data
        DriverEntity driver = driverRepository.findByUuid(DRIVER).orElseThrow();
        assertEquals(LocalDate.now(), driver.getLastCheckDriverLicence());
        assertEquals((Integer) 30, driver.getNextCheckDriverLicenceIn());
        assertEquals(2, driver.getDriverFiles(DRIVER_LICENSE).size());
        assertTrue(driver.getDriverFiles(DRIVER_LICENSE).stream()
            .map(DriverFileEntity::getFile)
            .map(FileEntity::getUuid)
            .allMatch(uuid -> uuid.equals(UUID.fromString(fileId1)) || uuid.equals(UUID.fromString(fileId2)))
        );
        assertEquals(2, fileRepository.count());
        assertEquals(2, driverFileRepository.count());

        /*
         * 4) as driver, I use the driver app to check one more time the whoAmI context, this time no new upload of files is needed
         */
        MvcResult resultDriverWhoAmI2 = mockMvc.perform(
                get("/api/whoami")
                    .header("Authorization", "Bearer " + driverToken.getValue())
            )
            .andExpect(status().isOk())
            .andReturn();

        String whoAmI2Json = resultDriverWhoAmI2.getResponse().getContentAsString();
        assertThat(whoAmI2Json, hasJsonPath("$.isDriverLicenceCheckNeeded", equalTo(false))); // file(s) upload must not be done

        /*
         * 5) as distributor, I see in dashboard, that driver uploaded today 2 files and when is the next time for upload planned
         */
        MvcResult resultDriverDetails = mockMvc.perform(
                get("/api/drivers/" + DRIVER)
                    .header("Authorization", "Bearer " + distributorToken.getValue())
            )
            .andExpect(status().isOk())
            .andReturn();

        String driverDetailsJson = resultDriverDetails.getResponse().getContentAsString();
        assertThat(driverDetailsJson, hasJsonPath("$.uuid", equalTo(DRIVER.toString()))); // file(s) upload must not be done
        assertThat(driverDetailsJson, hasJsonPath("$.firstName", equalTo("Cleo")));
        assertThat(driverDetailsJson, hasJsonPath("$.lastName", equalTo("Patra")));
        assertThat(driverDetailsJson, hasJsonPath("$.nextCheckDriverLicenceIn", equalTo(30)));
        assertThat(driverDetailsJson, hasJsonPath("$.lastCheckDriverLicence", equalTo(LocalDate.now().toString())));
        assertThat(driverDetailsJson, hasJsonPath("$.nextCheckDriverLicence", equalTo(LocalDate.now().plusDays(30).toString())));
        assertThat(driverDetailsJson, hasJsonPath("$.driverLicenceFiles.[*]", hasSize(2)));
        assertThat(driverDetailsJson, hasJsonPath("$.driverLicenceFiles.[0].uuid", equalTo(fileId1)));
        assertThat(driverDetailsJson, hasJsonPath("$.driverLicenceFiles.[1].uuid", equalTo(fileId2)));

        /*
         * 6) internal clean up, remove driver files directly in db and use cron job to remove data from file storage
         */
        // delete all driver files
        for (DriverFileEntity driverFile : driver.getDriverFiles()) driverFileRepository.deleteById(driverFile.getId());
        // driverFileRepository.flush();
        assertEquals(0, driverFileRepository.count());

        // use housekeeping cron job to remove unused files
        scheduledFileTasks.filesHouseKeeping();

        // check no more data
        assertEquals(0, fileRepository.count());
    }
}

I'm using zonky embeded database

pom.xml:

<!-- DATABASE STUFF -->
        <org.postgresql.version>42.2.25</org.postgresql.version>
        <org.flywaydb.version>8.5.2</org.flywaydb.version>
        <com.vladmihalcea.version>2.2.2</com.vladmihalcea.version>
        <zonky.embedded-database-spring-test.version>2.1.1</zonky.embedded-database-spring-test.version>
        <io.zonky.test.version>2.0.0</io.zonky.test.version>
        <org.flywaydb.flyway-test-extensions.version>7.0.0</org.flywaydb.flyway-test-extensions.version>
        <com.amazonaws.version>1.11.163</com.amazonaws.version>


        <dependency>
            <groupId>io.zonky.test</groupId>
            <artifactId>embedded-database-spring-test</artifactId>
            <version>${zonky.embedded-database-spring-test.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.zonky.test</groupId>
            <artifactId>embedded-postgres</artifactId>
            <version>${io.zonky.test.version}</version>
            <scope>test</scope>
        </dependency>

zonky configuration in application.yaml:

zonky:
    test:
        database:
            refresh: "before_class"

This is not the only test class which fails sometimes, only an example.

Tried restarting and reinstalling docker, rebuilding the project but nothing worked.

I will provide more information if needed.

Upvotes: 1

Views: 594

Answers (1)

M. Muhammadsodiq
M. Muhammadsodiq

Reputation: 135

I could not determine what is the real issue in your code. But a little suggestion. Sometimes EntityManager also throws this kind of issue. I mean that if you have used entityManager.close() method the application must not invoke any further methods on the EntityManager instance except for getTransaction and isOpen. Otherwise entityManager throws this java.lang.IllegalStateException. Please check that part also. Here is a link for entityManager.close()

Upvotes: 0

Related Questions