missionE46
missionE46

Reputation: 2522

Spring Context issue while running unit test

I am running some unit tests using Spring and Mockito. I have configured the mocks in the springcontext.xml as follow:

<bean id="featureEndpoint" class="org.mockito.Mockito" factory-method="mock">
    <constructor-arg value="com.company.blah.blah.FeatureEndpoint" />
</bean>

My test class is constructed as follow:

@ContextConfiguration(locations= {"/springcontext.xml"})
public class FeatureEndpointValidationTest extends JsonEndpointValidationTest {

    private FeatureEndpoint featureEndpoint;

    @BeforeClass
    public void setUp() {
        featureEndpoint = getBean("featureEndpoint");
        super.setEndpoint(featureEndpoint);
    }

    @Test
    .
    .
    .
}

When I run this test, getBean() throws an NPE because context is null. HOWEVER, if I rename the test class to say TestEndpoint (or anything that does not have the string 'Feature', it runs perfectly fine. Im flummoxed with this behaviour. I have searched all other config files for any naming clashes but none of them have any bean that contains the name 'feature'. Any clues as to why this is happening?

Here is the trace of the exception thrown:

java.lang.NullPointerException
    at com.foo.bar.UnitTest.getBean(UnitTest.java:14)
    at com.foo.bar.service.api.rest.FeatureEndpointValidationTest.setUp(FeatureEndpointValidationTest.java:30)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.testng.internal.MethodHelper.invokeMethod(MethodHelper.java:580)
    at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:398)
    at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:145)
    at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:82)
    at org.testng.internal.TestMethodWorker.invokeBeforeClassMethods(TestMethodWorker.java:167)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:104)
    at org.testng.TestRunner.runWorkers(TestRunner.java:712)
    at org.testng.TestRunner.privateRun(TestRunner.java:582)
    at org.testng.TestRunner.run(TestRunner.java:477)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:324)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:319)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:292)
    at org.testng.SuiteRunner.run(SuiteRunner.java:198)
    at org.testng.TestNG.createAndRunSuiteRunners(TestNG.java:821)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:788)
    at org.testng.TestNG.run(TestNG.java:708)
    at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:62)
    at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:141)
    at org.apache.maven.surefire.Surefire.run(Surefire.java:177)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:345)
    at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1009)

Thanks

Upvotes: 0

Views: 2284

Answers (1)

hisdrewness
hisdrewness

Reputation: 7651

You're using sprint-test, which is good. Try setting up your test like this:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:springcontext.xml)
public class MyTest {

    @Autowired
    private FeatureEndpoint featureEndpoint;

    @Test
    public void testSomething() { }

}

Using the @Autowired annotation with the Spring JUnit runner class, all autowired variables will be initialized to their corresponding bean of the same type. You can also use @Qualifier("featureEndpoint") to specify a bean name.

If you simply want access to the context, implement ApplicationContextAware which contains a setApplicationContext method.

Also, if you want to verify beans, you can implement InitializingBean, which, in a spring container, will be called after instantiation and initialization, where you can assert whether or not FeatureEndpoint is not null.

The key to this whole equation though is to use the SpringJUnit4ClassRunner runner class.

Upvotes: 1

Related Questions