Affects: spring-test
6.1.4
There is a bug, when using @Sql
with BEFORE_TEST_CLASS
.
Without this annotation the order of execution of methods is:
- method annotated with
@BeforeAll
- method annotated with
@DynamicPropertySource
- starting spring (often used to start some mock, then pass it to properties)
BUT when @Sql
with BEFORE_TEST_CLASS
is used, the order is:
- method annotated with
@DynamicPropertySource
- starting spring
- method annotated with
@BeforeAll
I have created sample repo: https://github.com/marwin1991/sql-before-class-bug-reproduction
with tests:
- https://github.com/marwin1991/sql-before-class-bug-reproduction/blob/main/src/test/java/com/github/marwin1991/sqlbeforeclassbugreproduction/WithoutSqlAnnotationTest.java
- https://github.com/marwin1991/sql-before-class-bug-reproduction/blob/main/src/test/java/com/github/marwin1991/sqlbeforeclassbugreproduction/WithSqlAnnotationTest.java
Second test not passing, because the order IMO is incorrect: it should not change after adding @Sql
.
Comment From: sbrannen
Hi @marwin1991,
Congratulations on submitting your first issue for the Spring Framework! 👍
The behavior you have described is not a bug but rather the expected behavior.
Spring cannot execute SQL scripts without access to the DataSource
/PlatformTransactionManager
from your ApplicationContext
.
When you use the BEFORE_TEST_CLASS
mode with @Sql
, the SqlScriptsTestExecutionListener
has to load the ApplicationContext
via the TestExecutionListener#beforeTestClass
callback, which is invoked before JUnit Jupiter @BeforeAll
lifecycle methods.
Since @DynamicPropertySource
methods are invoked when loading the ApplicationContext
, that means @DynamicPropertySource
methods are invoked before @BeforeAll
methods when using the BEFORE_TEST_CLASS
mode.
In other words, the invocation order of those methods is required to change when using the BEFORE_TEST_CLASS
mode.
Have you considered converting your @BeforeAll
method to a static
initialization block as follows?
static {
System.out.println("Calling init method");
var = 1;
// init here mock server f.e
// mockWebServer = new MockWebServer();
// mockWebServer.start();
}
Comment From: sbrannen
The Javadoc for ExecutionPhase.BEFORE_TEST_CLASS
currently states the following.
The configured SQL scripts and statements will be executed once per test class before any test method is run.
However, that is a bit misleading since one can infer that the SQL scripts and statements may be executed after "before class level" callbacks, which is not the case.
In light of that, I am repurposing this issue to improve the documentation.
Comment From: marwin1991
@sbrannen
Thank you for your clarification ❤️
I was thinking the order of sql BEFORE_TEST_CLASS is as follows: - method annotated with @BeforeAll - method annotated with @DynamicPropertySource - Spring is init (datasources and application context also) - SQL is executed - first test is executed
Comment From: sbrannen
@marwin1991, you can see the updated documentation here:
https://docs.spring.io/spring-framework/docs/6.1.5-SNAPSHOT/javadoc-api/org/springframework/test/context/jdbc/Sql.ExecutionPhase.html#BEFORE_TEST_CLASS
Comment From: marwin1991
@sbrannen 👍🏼