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:
The last test to run fails in all these scenarios:
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?
Not sure if you have found a solution to this but here is how I resolved this.
When the spring cached test contexts are reused the wiremock port changes back to that contexts port but seems to miss some step of configuring the WireMock
classes default server config. We had to call WireMock.configureFor(port)
in a @Before
or @BeforeEach
method with the port of the currently running context. This meant that when we did stubFor
method calls then the right WireMock port was hit and the server got configured with our stubs correctly, make sure you do this configuring before any resets too.
@Autowired
private Environment environment;
private String getWiremockServerPort() {
// Get the auto configured port property from the current Spring contexts environment
return environment.getProperty("wiremock.server.port");
}
@BeforeEach
private void configureWireMockPortToMatchEnvironmentContext() {
int contextEnvironmentPort = Integer.parseInt(getWiremockServerPort());
configureFor(contextEnvironmentPort);
}