[英]NullPointerException when stubbing a test method call with Mockito
我在单元测试中有以下两行:
DefaultMessageListenerContainer defaultMessageListenerContainer = Mockito.mock(DefaultMessageListenerContainer.class);
when(defaultMessageListenerContainer.isRunning()).thenReturn(true);
堆栈跟踪:
java.lang.NullPointerException
at org.springframework.jms.listener.AbstractJmsListeningContainer.isRunning(AbstractJmsListeningContainer.java:347)
at xxxxxxxxxxxxxx.MessageProcessorControllerTest.testPing(MessageProcessorControllerTest.java:109)
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:497)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:85)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:639)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:816)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1124)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:108)
at org.testng.TestRunner.privateRun(TestRunner.java:774)
at org.testng.TestRunner.run(TestRunner.java:624)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:359)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:354)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:312)
at org.testng.SuiteRunner.run(SuiteRunner.java:261)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1191)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1116)
at org.testng.TestNG.run(TestNG.java:1024)
at org.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:72)
at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:124)
不管我做什么,都会在上线when
抛出NPE,就像在设置存根时调用了真正的方法一样。 我正在使用Mockito v1.10.19。 我究竟做错了什么?
更新:这是整个独立测试类:
import org.mockito.Mockito;
import org.springframework.jms.listener.DefaultMessageListenerContainer;
import org.testng.annotations.Test;
import static org.mockito.Mockito.when;
public class JmsTest {
@Test
public void test() throws Exception {
DefaultMessageListenerContainer defaultMessageListenerContainer = Mockito.mock(
DefaultMessageListenerContainer.class);
when(defaultMessageListenerContainer.isRunning()).thenReturn(true);
}
}
并抛出异常:
java.lang.NullPointerException
at org.springframework.jms.listener.AbstractJmsListeningContainer.isRunning(AbstractJmsListeningContainer.java:347)
at xxxxxxxxxxx.util.JmsTest.test(JmsTest.java:17)
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:497)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:85)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:639)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:816)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1124)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:108)
at org.testng.TestRunner.privateRun(TestRunner.java:774)
at org.testng.TestRunner.run(TestRunner.java:624)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:359)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:354)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:312)
at org.testng.SuiteRunner.run(SuiteRunner.java:261)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1191)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1116)
at org.testng.TestNG.run(TestNG.java:1024)
at org.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:72)
at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:124)
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:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
您的defaultMessageListenerContainer
不是正在使用的那个。 失败的是类型AbstractJmsListeningContainer
。
您需要确保已将模拟变量正确传递给您要测试的类。
那是一个好人! 我曾期望该测试能够通过,因为它似乎只会设定期望值,而不会做出任何断言。 我想我会把它交给Mockito专家,以解决为什么看起来非常简单的练习不起作用的原因。 我当然想知道它的背后是什么。 同时,如果您可以选择使用其他库,那么我将建议您:尝试使用JMockit。 以下内容应大致相当于您想使用Mockito实现的功能...但是测试通过了。 祝好运!
import mockit.Expectations;
import mockit.Mocked;
import org.junit.Test;
import org.springframework.jms.listener.DefaultMessageListenerContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class JmsTest2 {
@Mocked
DefaultMessageListenerContainer defaultMessageListenerContainer;
@Test
public void test() throws Exception {
new Expectations() {{
defaultMessageListenerContainer.isRunning(); result = true;
}};
assertThat(defaultMessageListenerContainer.isRunning()).isTrue();
}
}
编辑1:
仔细研究一下,似乎在标记为final的对象的isRunning()方法中存在一些同步。 在您将要更改的对象标记为final的情况下,AFAIK的Mockito往往无济于事。 您可以尝试与PowerMock对抗,或者使用其他库(我已经建议过我喜欢的库),我认为这对您来说是一种干净,简单的方法。
protected final Object lifecycleMonitor = new Object();
...
@Override
public final boolean isRunning() {
synchronized (this.lifecycleMonitor) {
return (this.running && runningAllowed());
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.