I'm experiencing a strange exception when I run a test suite:
Caused by: org.springframework.boot.context.embedded.tomcat.ConnectorStartFailedException:
Connector configured to listen on port 9109 failed to start
The following message is logged:
***************************
APPLICATION FAILED TO START
***************************
Description:
The Tomcat connector configured to listen on port 9109 failed to start. The port may already be in use or the connector may be misconfigured.
Action:
Verify the connector's configuration, identify and stop any process that's listening on port 9109, or configure this application to listen on another port.
The root cause seems to be the following:
java.net.BindException: Address already in use
1.5.6.RELEASE
I was able to reproduce the problem with the following classes:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ApplicationBootstrap.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@TestPropertySource(locations = "classpath:integration-test.properties")
public abstract class BaseTest {
}
public class Test1 extends BaseTest {
@Test
public void test1() {
System.out.println("foo");
}
}
@TestPropertySource(properties = "NEW_PROPERTY=true")
public class Test2 extends BaseTest {
@Test
public void test2() {
System.out.println("bar");
}
}
When I run all the tests, Test1 is run first without issue and then it looks as if the application context is refreshed before Test2 is run. Test2 fails with
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by the ConnectorStartFailedException described above
This is working as designed. Spring Framework's test framework will, by default, cache contexts for possible reuse by multiple test classes. You have two tests with different configuration (due to @TestPropertySource) so they will use different application contexts. The context for the first test will be cached and kept open while the second test is running. Both tests are configured to use the same port for Tomcat's connector. As a result, when the second test is run, the context fails to start due to a port clash with the connector from the first test. You have a few options:
RANDOM_PORT@TestPropertySource from Test2 so that the contexts have identical configuration and the context from the first test can be reused for the second test.@DirtiesContext so that the context isn't cachedIf you require further guidance, please follow up on Stack Overflow or Gitter.
I wouldnt be so quick to write this off as invalid
RANDOM_PORT in this case as the port needs to be predictable@TestPropertySource@DirtiesContext does fix the issue, it makes the tests very slow as it forces a refresh of the application context for each test class so I wouldnt accept that as a solutionThis is working as designed
I have used this pattern with earlier versions of spring boot and it works
The application context seems to be refreshed when Test2 is run as there is a new property, but it looks like it doesnt clean to the extent of @DirtiesContext. Is there a way to fix this?
I have used this pattern with earlier versions of spring boot and it works
I can't think how that could be. If you have two contexts that are cached and kept open, both configured to use the same port they will fail with a port clash. If you can provide an example of the pattern working with earlier versions of Boot then we can investigate further.
The application context seems to be refreshed when Test2 is run as there is a new property, but it looks like it doesnt clean to the extent of @DirtiesContext. Is there a way to fix this?
No. There's no cleaning going on. There are two application contexts and the second context is refreshed while the first is cached and kept open. @DirtiesContext prevents the context from being cached and kept open.
No. There's no cleaning going on. There are two application contexts and the second context is refreshed while the first is cached and kept open. @DirtiesContext prevents the context from being cached and kept open.
Oh I see. A lack of understanding on my part.
I have used this pattern with earlier versions of spring boot and it works
It turns out that while I was using @TestPropertySource without issue, the server was configured with a random port so there was no conflicts.
It seems that I need to rethink my approach. Thanks for your help 馃槂
Most helpful comment
This is working as designed. Spring Framework's test framework will, by default, cache contexts for possible reuse by multiple test classes. You have two tests with different configuration (due to
@TestPropertySource) so they will use different application contexts. The context for the first test will be cached and kept open while the second test is running. Both tests are configured to use the same port for Tomcat's connector. As a result, when the second test is run, the context fails to start due to a port clash with the connector from the first test. You have a few options:RANDOM_PORT@TestPropertySourcefromTest2so that the contexts have identical configuration and the context from the first test can be reused for the second test.@DirtiesContextso that the context isn't cachedIf you require further guidance, please follow up on Stack Overflow or Gitter.