I am running a spring boot application that uses TestNG as the testing framework. My tests are set up like this:
A parent class, which is in charge of setup logic and takes care of all of the configuration stuffs:
@ContextConfiguration(classes = {TestingConfig.class}, initializers = ConfigFileApplicationContextInitializer.class)
@ContextConfiguration(classes = TestConfig.class)
@TestPropertySource(locations = "classpath:application.yml")
public abstract ParentTestClass extends AbstractTestNGSpringContextTests {
@Autowired
private ServiceClient serviceClient;
@BeforeSuite
public void beforeClass() {
Assert.assertNotNull(serviceClient);
serviceClient.doSomeSetupWork();
}
}
There are multiple child test classes. Each on inherits form the parent test class so that they share the same setup logic.
public ChildTestClass1 extends ParentTestClass {
@Test
public void someTest() {
...
}
// More tests not shown
}
public ChildTestClass2 extends ParentTestClass {
@Test
public void anotherTest() {
...
}
// More tests not shown
}
The serviceClient
is a client for one of the web services that the test suite depends on. I am making calls with the service client to set up the data in the other service before running the test cases.
The problem is this: previously I was using the @BeforeClass
annotation, which meant that the parent class's setup method was being run once for every child test class. This was ok, but it was really slow waiting for the same setup to be run multiple times.
So I thought to myself: I'll just change the @BeforeClass
annotations in the ParentTestClass to be @BeforeSuite
instead! That will solve all of my problems!
Wrong.
Now when I run it, the Assert.assertNotNull(serviceClient);
line in the beforeClass()
method of the parent class fails. In short, Spring dependencies aren't being injected into the @BeforeSuite annotated method, even tho they were being injected in the method when it was annotated with @BeforeClass
.
Any thoughts here? I'd really appreciate it!
I believe this is working as designed. From looking at how the implementation is built within org.springframework.test.context.testng.AbstractTestNGSpringContextTests
(from which you extend), the dependencies are injected into your test class via the org.springframework.test.context.support.DependencyInjectionTestExecutionListener#injectDependencies
(this is a listener).
All the listeners including the DependencyInjectionTestExecutionListener
is invoked only via org.springframework.test.context.testng.AbstractTestNGSpringContextTests#springTestContextPrepareTestInstance
which is a @BeforeClass(alwaysRun=true)
classified method.
So your dependencies aren't available to you until and unless this @BeforeClass
annotated method runs to completion. So you would have to move out your @BeforeSuite
method and have it work with a @BeforeClass
annotation only.
If you don't need your service setup to be done multiple times, then you would need to add an edit check in your test code that does the setup ONLY IF ITS NOT DONE.
Here is the solution to all your problem.
@Override
@BeforeSuite
protected void springTestContextPrepareTestInstance() throws Exception {
super.springTestContextPrepareTestInstance();
}
Hope this helps you to inject the dependencies.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With