Here's how I implemented this to setup some test data in my database using a dataSource
Spring bean, by combining Sam's answer above with this answer: https://stackoverflow.com/a/51556718/278800
import javax.sql.DataSource;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.junit.jupiter.SpringExtension;
public class TestDataSetup implements BeforeAllCallback, ExtensionContext.Store.CloseableResource {
private static boolean started = false;
private DataSource dataSource;
@Override
public void beforeAll(ExtensionContext extensionContext) {
synchronized (TestDataSetup.class) {
if (!started) {
started = true;
// get the dataSource bean from the spring context
ApplicationContext springContext = SpringExtension.getApplicationContext(extensionContext);
this.dataSource = springContext.getBean(DataSource.class);
// TODO: put your one-time db initialization code here
// register a callback hook for when the root test context is shut down
extensionContext
.getRoot()
.getStore(ExtensionContext.Namespace.GLOBAL)
.put("TestDataSetup-started", this);
}
}
}
@Override
public void close() {
synchronized (TestDataSetup.class) {
// TODO: put your db cleanup code here
}
}
(I'm not 100% sure on the thread safety of this, so I added the synchronized
block just to be safe.)
To enable this extension, you just need to add this annotation to your test classes which need it:
@ExtendWith(TestDataSetup.class)
The nice thing is that Junit 5 allows multiple extensions, so this works even if your tests are already annotated with @ExtendWith(SpringExtension.class)
.