Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring dependencies not being injected into BeforeSuite method?

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!

like image 476
teuber789 Avatar asked Mar 23 '17 22:03

teuber789


2 Answers

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.

like image 155
Krishnan Mahadevan Avatar answered Oct 22 '22 12:10

Krishnan Mahadevan


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.

like image 41
suro230791 Avatar answered Oct 22 '22 14:10

suro230791