首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SSLContext模拟行为不像预期的那样

SSLContext模拟行为不像预期的那样
EN

Stack Overflow用户
提问于 2016-07-11 18:26:28
回答 1查看 5.6K关注 0票数 2

我有以下简单的类:导入javax.net.ssl.SSLContext;

代码语言:javascript
复制
public class AClass {
    public void someMethod() throws Exception {
        SSLContext context = SSLContext.getInstance("SSL");
        context.init(null, null, null);
    }
}

及其JUnit:进口javax.net.ssl.SSLContext;

代码语言:javascript
复制
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失败:

代码语言:javascript
复制
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()这样的void方法不应该做任何事情。那么,它为什么要抛出一个NullPointerException

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-07-18 09:59:27

查看API接口并对抛出NPEinit方法进行反编译签名,它显示为final,它是basic Mockito.mock()无法处理

另一方面,PowerMockito.mock()的javadoc读取:

org.powermock.api.mockito.PowerMockito 公共静态T模拟(类类型) 创建一个模拟对象,该对象支持对最终方法和本机方法的模拟。类型参数: mock模拟对象的类型 参数: 非匹配类型-模拟对象的类型 返回: 与模拟对象相对应。

所以,稍微改变一下你的测试应该能让它发挥作用:

代码语言:javascript
复制
@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运行测试,所以您也可以替换

代码语言:javascript
复制
SSLContext context = PowerMockito.mock(SSLContext.class);

带着一块田

代码语言:javascript
复制
@Mock
private SSLContext context;

它也将由PowerMock处理(如果您只需要基本的mockito,则使用MockitoJUnitRunner )。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38313726

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档