While @DynamicPropertySource
is great, it would be even better if it could be executed on each @Test
method instead only one time at start of the test class.
For example: okhttp MockWebServer
starts on a free random port. But each test needs its own MockWebServer
as otherwise the state is preserved between test runs.
@SpringBootTest
public class MockTest implements BeforeEachCallback {
private MockWebServer mockServer;
//requires a fresh instance for each @Test method
@Override
public void beforeEach(ExtensionContext extensionContext) {
mockServer = new MockWebServer();
}
//this is not possible as mockServer is not static!
@DynamicPropertySource
static void changePort(DynamicPropertyRegistry registry) {
registry.add("my.app.base.url", () -> "http://localhost:" + mockServer.getPort());
}
}
If I'd make the MockWebServer
a static
field, that won't work if multiple @Test
classes make use of the mock. Eg assertEquals(1, mockServer.getRequestCount());
would only be valid for the first test method, as mockwebserver preserves the state then.
Comment From: sbrannen
Unfortunately, it is not currently possible to make the @DynamicPropertySource
non-static, since the Spring TestContext Framework has no access to the test class instance when a ContextCustomizer
is invoked (which is how the support for @DynamicPropertySource
is implemented).
If we were to implement #16647, it may become possible, but at this time it is not possible.
Have you considered applying @DirtiesContext
on a per-test-method basis to have the ApplicationContext
reloaded for each individual test method?
Comment From: sbrannen
- blocked by #16647
Comment From: membersound
@DirtiesContext
is a nice idea, anyhow this would reinitialize any beans inside the test. Eg database/testcontainers or similar, which might be quite expensive if recreated for each @Test
.
Comment From: sbrannen
@DirtiesContext
is a nice idea, anyhow this would reinitialize any beans inside the test. Eg database/testcontainers or similar, which might be quite expensive if recreated for each@Test
.
Well, if we were to support @DynamicPropertySource
on non-static fields, how would that effectively be any different?
Spring components that consume the dynamic properties would typically be initialized with such dynamic properties when the ApplicationContext
is created. Thus, without recreating the ApplicationContext
, most (if not all) consumers of those dynamic properties would not see a change to their values.
Perhaps something like test-scoped beans (see #18606) would better suit your needs?
Comment From: membersound
Ok, so but testscoped beans have been closed without any implementation?
Is it maybe possible to declare my service that makes use of the "dynamic" @Value("${my.app.base.url}")
as test-scoped? So that it rereads the dynamic property from application-context?
Comment From: sbrannen
Ok, so but testscoped beans have been closed without any implementation?
That's correct. That issue was bulk closed due to lack of interest.
Is it maybe possible to declare my service that makes use of the "dynamic"
@Value("${my.app.base.url}")
as test-scoped? So that it rereads the dynamic property from application-context?
That's what I had in mind. Your use case reminded me of that test-scoped bean proposal.
And your use case would likely be a candidate for re-opening that issue. So feel free to request that it be reopened if you feel strongly about it, and we can revisit the idea.