I have the following scenario:
@Transactional
@SpringBootTest
@ActiveProfiles("test")
@AutoConfigureMockMvc
@AutoConfigureWireMock(port = 0)
public abstract class IntegrationTest {
}
public class Test1 extends IntegrationTest {
// Tests that use WireMock
}
@ActiveProfiles("specific-case-test") // This causes another Application Context to be created.
public class Test2 extends IntegrationTest {
// Tests that use WireMock
}
public class Test3 extends IntegrationTest {
// Tests that use WireMock
}
Tests run successfully in all these scenarios:
- Run the tests individually
- In the order: Test1, Test3, Test2
- In the order: Test3, Test1, Test2
- In the order: Test2, Test3, Test1
- In the order: Test2, Test1, Test3
The last test to run fails in all these scenarios:
- In the order: Test1, Test2, Test3
- In the order: Test3, Test2, Test1
I already investigated the problem and it is related to the Spring Application Context and WireMock.
What is going on? Let's consider that the tests run in that order: Test1, Test2, Test3
.
When Test1
runs, an Application Context (AC1) is created and a WireMock server (WM1) is set up, let's say, on port 1. Port 1 is set to AC1 (wiremock.server.port
) and WM1 is attached to the test thread. All test passes.
When Test2
runs, another Application Context (AC2) is created and a new WireMock server (WM2) is set up, let's say, on port 2. Port 2 is set to AC2 (wiremock.server.port
) and WM2 is attached to the test thread, replacing WM1. All test passes.
When Test3
runs, it reuses AC1 and this causes the tests to fail with the message: 404 Not Found: [No response could be served as there are no stub mappings in this WireMock instance.]
.
The application state is that wiremock.server.port
is 1 (comes from AC1) and WM2 is attached to the test thread. Because of that, stubbing happens against WM2, but the application rest calls are going to WM1, which is listening on port 1.
I already tried to clean the Application Context adding @DirtiesContext
to Test2, so it would force Spring to load the third AC, but it doesn't work. However, if I add @DirtiesContext
to Test1 or @DirtiesContext(classMode = BEFORE_CLASS)
to Test3 it works. I don't want this solution because I have other tests and there is no guarantee in which order the tests will run, so if I add it to Test3, then later the execution order will change and another test will fail. I would like a real solution.
Any ideas?