-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Controlling execution order of JUnit 5 extension relative to other extensions not possible #1017
Comments
Probably related to #1019. |
I created a reproducer in https://github.com/jrehwaldt/testcontainers-gh1017 The issue when using Kotlin is not the annotation order (maybe in Java it is as per JUnit documentation?), but instead that Spring will load the context very early in case of bean injection into the constructor. Doesn't work: @SpringBootApplication
class Application
@Component
class SomeSimpleBean
@Testcontainers // Has to run before SpringBootTest (SpringExtension) is run,
@SpringBootTest // but because of <constructorInjectedBean> below this doesn't happen.
@ContextConfiguration(initializers = [TestcontainersIssueGh1017ConstructorInjection.DynamoDbAwareInitializer::class])
class TestcontainersIssueGh1017ConstructorInjection(
@Autowired private val constructorInjectedBean: SomeSimpleBean
) {
companion object {
@Container
private val dynamodb = KGenericContainer("richnorth/dynalite:latest")
.withExposedPorts(4567)
}
@Test
fun `should execute TestcontainerExtension before SpringExtention`() {
// When we reach here we're fine
}
internal class DynamoDbAwareInitializer : ApplicationContextInitializer<ConfigurableApplicationContext> {
override fun initialize(context: ConfigurableApplicationContext) {
// FIXME Next line will fail with
// > java.lang.IllegalStateException: Mapped port can only be obtained after the container is started
val dynamodbEndpoint = "http://${dynamodb.containerIpAddress}:${dynamodb.getMappedPort(4567)}"
TestPropertyValues.of(
"aws.dynamodb.endpoint: $dynamodbEndpoint",
"aws.dynamodb.create-tables: true"
).applyTo(context)
}
}
} Works as expected: @Testcontainers // Runs before SpringBootTest as expected
@SpringBootTest // when using field injection.
@ContextConfiguration(initializers = [TestcontainersIssueGh1017FieldInjection.DynamoDbAwareInitializer::class])
class TestcontainersIssueGh1017FieldInjection {
companion object {
@Container
private val dynamodb = KGenericContainer("richnorth/dynalite:latest")
.withExposedPorts(4567)
}
@Autowired
private lateinit var fieldInjectedBean: SomeSimpleBean
@Test
fun `should execute TestcontainerExtension before SpringExtention`() {
// When we reach here we're fine
}
internal class DynamoDbAwareInitializer : ApplicationContextInitializer<ConfigurableApplicationContext> {
override fun initialize(context: ConfigurableApplicationContext) {
val dynamodbEndpoint = "http://${dynamodb.containerIpAddress}:${dynamodb.getMappedPort(4567)}"
Thread.sleep(1000)
TestPropertyValues.of(
"aws.dynamodb.endpoint: $dynamodbEndpoint"
).applyTo(context)
}
}
} Changing the annotation order between All four tests are green when running against #1020. |
Thanks a lot for checking against #1020. |
@kiview @michael-simons I'm trying to write a new JUnit Jupiter extension that builds on top of the Testcontainers extension. The original solution proposed in this issue (make @Target(TYPE)
@Retention(RUNTIME)
@ExtendWith({TestContainerExtension.class, MyExtension.class})
public @interface MyExt { } I'm trying to follow the various issues linked in this issue to find out why the |
@aguibert asked right question, @kiview @michael-simons why aren't TestcontainersExtension and related classes public? |
I am trying to use this extension together with
@SpringBootTest
. How to ensure testcontainer starts first before executingSpringBootTest
extension?This issue is not limited to Spring, but rather an issue as soon as multiple extensions are used at the same time and a certain ordering is required.
Context
From what I see in the JUnit 5 documentation the annotation order matters. Since Java sorts annotations in bytecode alphabetically Spring will always run first unless it is possible to explicitly import
@ExtendWith(TestcontainersExtension.class)
. Currently, this cannot be done due toTestcontainersExtension
being package-private.Possible solution
I believe making
TestcontainersExtension
public is all that's needed for users to be able to explicitly define the order of multiple extensions.Based on #887 (comment) and #887 (comment).
The text was updated successfully, but these errors were encountered: