2016-07-11 112 views
1

我有以下简单的类: import javax.net.ssl.SSLContext;SSLContext模拟不如预期

public class AClass { 
    public void someMethod() throws Exception { 
     SSLContext context = SSLContext.getInstance("SSL"); 
     context.init(null, null, null); 
    } 
} 

而且它的JUnit: 进口javax.net.ssl.SSLContext;

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.mockito.Mockito; 
import org.powermock.api.mockito.PowerMockito; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.PowerMockRunner; 

@RunWith(PowerMockRunner.class) 
@PrepareForTest({ SSLContext.class }) 
public class ATest { 
    @Test 
    public void testSomeMethod() throws Exception { 
     PowerMockito.mockStatic(SSLContext.class); 
     SSLContext context = Mockito.mock(SSLContext.class); 
     Mockito.when(context.getInstance("SSL")).thenReturn(context); 
     new AClass().someMethod(); 
    } 
} 

JUnit的失败,出现以下堆栈跟踪:

java.lang.NullPointerException 
    at javax.net.ssl.SSLContext.init(Unknown Source) 
    at random.AClass.someMethod(AClass.java:8) 
    at random.ATest.testSomeMethod(ATest.java:20) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:316) 
    at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:89) 
    at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:97) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:300) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:131) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.access$100(PowerMockJUnit47RunnerDelegateImpl.java:59) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner$TestExecutorStatement.evaluate(PowerMockJUnit47RunnerDelegateImpl.java:147) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.evaluateStatement(PowerMockJUnit47RunnerDelegateImpl.java:107) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:288) 
    at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:87) 
    at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:50) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:208) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:147) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:121) 
    at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34) 
    at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:123) 
    at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:121) 
    at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53) 
    at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) 

堆栈跟踪点到行与具有一个空指针context.init(null, null, null);。但是,当我调试(在Eclipse中)时,我可以清楚地看到context变量的值是Mock for SSLContext, hashCode: 1857173583。如果模拟,那么像init()这样的无效方法不应该做任何事情。那么,为什么投掷NullPointerException

回答

2

寻找在用于init方法,其抛出NPEAPI和反编译签名,它显示为最终,其基本Mockito.mock() can not handle

Final method

在另一方面,对于PowerMockito.mock()的Javadoc读取:

org.powermock.api.mockito.PowerMockito

公共静态Ť模拟(类型)
创建支持的最终嘲笑一个模拟对象和本地方法。

类型参数:
       笔 - 类型的模拟对象的
参数:
       型 - 模拟对象的类型
返回:
       模拟目的。

所以,改变了一下您的测试应该使其工作:

@RunWith(PowerMockRunner.class) 
@PrepareForTest({SSLContext.class}) 
public class ATest { 
    @Test 
    public void testSomeMethod() throws Exception { 
     // create the mock to return by getInstance() 
     SSLContext context = PowerMockito.mock(SSLContext.class); 

     // mock the static method getInstance() to return above created mock context 
     PowerMockito.mockStatic(SSLContext.class); 
     Mockito.when(SSLContext.getInstance("SSL")).thenReturn(context); 

     // invoke the object under test 
     new AClass().someMethod(); 

     //TODO - add verifications/assertions 
    } 
} 

更新:

既然你与PowerMockRunner运行测试,你也可代替

SSLContext context = PowerMockito.mock(SSLContext.class); 

与现场

@Mock 
private SSLContext context; 

这也将PowerMock处理(或使用MockitoJUnitRunner如果你只需要基本的Mockito)

+0

一直以为'PowerMockito.mock()'&'Mockito.mock( )'是一样的。感谢您指出! – Vineet

+1

@Vineet毫无问题,确实它们是[类似的](http://i.imgur.com/pIvKZxD.gif),powermock在mockito的基础上增加了更多的功能。另外我用第二种方法更新了答案。 – Morfic