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

我是研究僧i 提交于 2019-12-11 06:11:46

问题


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

回答1:


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 :

  • Configure TestNG to use the PowerMock object factory : You can do this either via the attribute object-factory in your <suite> tag of your suite xml or via an @org.testng.annotations.ObjectFactory annotated method which returns the powermock's implementation of TestNG interface org.testng.IObjectFactory viz., org.powermock.modules.testng.PowerMockObjectFactory (or) by extending org.powermock.modules.testng.PowerMockTestCase
  • Use @PrepareForTest to prepare your static class for being mocked by PowerMockit

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})


来源:https://stackoverflow.com/questions/45528317/issue-when-test-a-jersey-rest-service-using-powermock-with-jersey-test-testng

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!