6

I would like to register some web scopes to the spring context in my @BeforeTest method. But it turns out that spring context is still null at that point.

The test runs fine though, if I change into @BeforeMethod. I wonder how I can access the context in @BeforeTest, because I don't want the scope registration code to be repeated for each test methods.

Below are my code snippets.

public class MyTest extends MyBaseTest {
    @Test public void someTest() { /*...*/ }
}

@ContextConfiguration(locations="/my-context.xml")
public class MyBaseTest extends AbstractTestNGSpringContextTests {
    @BeforeTest public void registerWebScopes() {
        ConfigurableBeanFactory factory = (ConfigurableBeanFactory)
                this.applicationContext.getAutowireCapableBeanFactory();
        factory.registerScope("session", new SessionScope());
        factory.registerScope("request", new RequestScope());
    }   

    /* some protected methods here */
}

Here's the error message when running the test:

FAILED CONFIGURATION: @BeforeTest registerWebScopes
java.lang.NullPointerException
    at my.MyBaseTest.registerWebScopes(MyBaseTest.java:22)
kuporific
  • 10,053
  • 3
  • 42
  • 46
Bertie
  • 17,277
  • 45
  • 129
  • 182

2 Answers2

12

Call springTestContextPrepareTestInstance() in your BeforeTest method.

Joe Snikeris
  • 1,150
  • 12
  • 17
5

TestNG runs @BeforeTest methods before @BeforeClass methods. The springTestContextPrepareTestInstance() is annotated with @BeforeClass and sets up the applicationContext. This is why the applicationContext is still null in a @BeforeTest method. @BeforeTest is for wapping a tagged group of tests. (It does not run before each @Test method, so it's a bit of a misnomer).

Instead of using @BeforeTest, you should probably use @BeforeClass (which is run once, before the first @Test in the current class). Be sure it depends on springTestContextPrepareTestInstance method, as in

@BeforeClass(dependsOnMethods = "springTestContextPrepareTestInstance")
public void registerWebScopes() {
    ConfigurableBeanFactory factory = (ConfigurableBeanFactory) 
            this.applicationContext.getAutowireCapableBeanFactory();
    factory.registerScope("session", new SessionScope());
    factory.registerScope("request", new RequestScope());
}   

The @BeforeMethod works, too (as you mentioned) because they run after @BeforeClass methods.

kuporific
  • 10,053
  • 3
  • 42
  • 46
  • "`@BeforeClass` (run before any `@Tests` in the current class)". <-- This is incorrect. As stated in [TestNG documentation](http://testng.org/doc/documentation-main.html), `@BeforeClass` will be run before the **first** test method in the current class is invoked. – JonyD Sep 25 '17 at 14:22
  • @JonyD, thanks for pointing this out, the wording is not clear. I've edited it based on your suggestion. – kuporific Sep 25 '17 at 16:30