testngpowermockintegration-testingjersey-test-framework

Issue when test a Jersey rest service using powermock with Jersey Test + TestNg


A rest service using Jersey developed. Now I want to write some integration tests for this web service but since not every class being used from the web service is already implemented I need to mock some of them. For example I have the following class:

public class ServiceA {

public String getService() {
    return null;
}}

@Path("/myresource")
public class ResourceController {

@GET 
@Produces("text/plain")
public String getIt() {
    ServiceA a = new ServiceA();
    return a.getService();
}}

Then i want to test do integration test with Jersey test framework and TestNg + Powermock (mock new object with constructor).

import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTestNg;
import org.glassfish.jersey.test.jdkhttp.JdkHttpServerTestContainerFactory;
import org.glassfish.jersey.test.spi.TestContainerFactory;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.testng.PowerMockObjectFactory;
import org.testng.Assert;
import org.testng.IObjectFactory;
import org.testng.annotations.ObjectFactory;
import org.testng.annotations.Test;

import javax.ws.rs.core.Application;
import javax.ws.rs.core.Response;

import static org.powermock.api.mockito.PowerMockito.mock;

    @PowerMockIgnore({"javax.ws.*", "org.glassfish.*"})
    @PrepareForTest({ResourceController.class})
        public class ResourceControllerTest extends JerseyTestNg.ContainerPerMethodTest {
       @Override
        protected Application configure() {
            return new ResourceConfig(ResourceController.class);
        }

        @Override
        protected TestContainerFactory getTestContainerFactory() {
            return new JdkHttpServerTestContainerFactory();
        }

@ObjectFactory
public IObjectFactory getObjectFactory() {
    return new PowerMockObjectFactory();
}


        @Test
        public void getItTest() {
            ServiceA mockA = mock(ServiceA.class);
            Mockito.when(mockA.getService()).thenReturn("service a");
  PowerMockito.whenNew(ServiceA.class).withAnyArguments().thenReturn(mockA);
            Response result = target("myresource").request().get();
            Assert.assertEquals(result.readEntity(String.class), "service a");
        }
    }

My pom dependecy:

    <dependency>
            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
            <artifactId>jersey-test-framework-provider-inmemory</artifactId>
            <version>2.21</version>
        </dependency> 

        <dependency>
            <groupId>org.glassfish.jersey.test-framework</groupId>
            <artifactId>jersey-test-framework-core</artifactId>
            <version>2.21</version>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-module-testng</artifactId>
            <version>1.7.0</version>
            <scope>test</scope>
        </dependency>
<dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-api-mockito</artifactId>
            <version>1.7.0</version>
            <scope>test</scope>
        </dependency>

But in runtime, the instance ServiceA in getIt() method is still initalized as new ServiceA object not the mockA object.

Any idea about it? Thanks,

if add PowerMockIgnore({"javax.ws.", "org.glassfish."}), then see below exception:

java.lang.ExceptionInInitializerError
    at org.mockito.internal.exceptions.stacktrace.ConditionalStackTraceFilter.<init>(ConditionalStackTraceFilter.java:17)
    at org.mockito.exceptions.base.MockitoException.filterStackTrace(MockitoException.java:41)
    at org.mockito.exceptions.base.MockitoException.<init>(MockitoException.java:30)
    at org.mockito.exceptions.misusing.MockitoConfigurationException.<init>(MockitoConfigurationException.java:18)
    at org.mockito.internal.configuration.plugins.PluginLoader.loadImpl(PluginLoader.java:66)
    at org.mockito.internal.configuration.plugins.PluginLoader.loadPlugin(PluginLoader.java:24)
    at org.mockito.internal.configuration.plugins.PluginRegistry.<init>(PluginRegistry.java:12)
    at org.mockito.internal.configuration.plugins.Plugins.<clinit>(Plugins.java:11)
    at org.mockito.internal.util.MockUtil.<clinit>(MockUtil.java:24)
    at org.mockito.internal.configuration.injection.scanner.MockScanner.<init>(MockScanner.java:22)
    at org.mockito.internal.configuration.InjectingAnnotationEngine.injectMocks(InjectingAnnotationEngine.java:96)
    at org.powermock.api.mockito.internal.configuration.PowerMockitoInjectingAnnotationEngine.process(PowerMockitoInjectingAnnotationEngine.java:35)
    at org.powermock.api.extension.listener.AnnotationEnabler.injectSpiesAndInjectToSetters(AnnotationEnabler.java:72)
    at org.powermock.api.extension.listener.AnnotationEnabler.beforeTestMethod(AnnotationEnabler.java:64)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.powermock.reflect.internal.WhiteboxImpl.performMethodInvocation(WhiteboxImpl.java:1846)
    at org.powermock.reflect.internal.WhiteboxImpl.invokeMethod(WhiteboxImpl.java:700)
    at org.powermock.reflect.Whitebox.invokeMethod(Whitebox.java:415)
    at org.powermock.modules.testng.internal.PowerMockTestNGMethodHandler.injectMocksUsingAnnotationEnabler(PowerMockTestNGMethodHandler.java:76)
    at org.powermock.modules.testng.internal.PowerMockTestNGMethodHandler.invoke(PowerMockTestNGMethodHandler.java:48)
    at com.hp.ucmdb.rest.ResourceControllerTest_$$_jvstb11_0.setUp(ResourceControllerTest_$$_jvstb11_0.java)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:86)
    at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:514)
    at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:215)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:589)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:820)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1128)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:129)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:112)
    at org.testng.TestRunner.privateRun(TestRunner.java:782)
    at org.testng.TestRunner.run(TestRunner.java:632)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:366)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:361)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:319)
    at org.testng.SuiteRunner.run(SuiteRunner.java:268)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1244)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1169)
    at org.testng.TestNG.run(TestNG.java:1064)
    at org.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:72)
    at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:127)
Caused by: java.lang.NullPointerException
    at org.mockito.internal.configuration.plugins.Plugins.getStackTraceCleanerProvider(Plugins.java:17)
    at org.mockito.internal.exceptions.stacktrace.StackTraceFilter.<clinit>(StackTraceFilter.java:21)
    ... 49 more

Solution

  • I believe the mock is perhaps not happening because you dont have the PowerMock's objectfactory implementation wired into TestNG.

    In order to get powermockito and TestNG to work with each other you have to do the following :

    I couldnt find any reference to you using the PowerMock's Object factory wiring in, in your code. Can you please try doing that and see if that helps ?

    Please see here for full details.

    Update: In order to get past the ClassCastExceptions you would need to add the below annotation to your class.

    @org.powermock.core.classloader.annotations.PowerMockIgnore({"javax.ws.*", "org.glassfish.*"})
    

    For more details around this, please refer to this stackoverflow question

    PS : I am assuming that you are using the following annotation to have powermock prepare your test class for mocking (Your sample in your question is showing something else)

    @org.powermock.core.classloader.annotations.PrepareForTest({ResourceController.class})