java – 为什么void方法在模拟对象上获得NullPointerException?
我正在为我的
java应用程序编写单元测试,该应用程序分析对Stash的提交,这是一个类似于
Github的atlassian应用程序.
我正在测试的方法是这样的: public List<Message> processEvent(RepositoryRefsChangedEvent event) { ArrayList<Message> commitList = new ArrayList<Message>(); for (RefChange refChange : event.getRefChanges()) { LOGGER.info("checking ref change refId={} fromHash={} toHash={} type={}",refChange.getRefId(),refChange.getFromHash(),refChange.getToHash(),refChange.getType()); if (refChange.getRefId().startsWith(REF_BRANCH)) { if (refChange.getType() == RefChangeType.ADD && isDeleted(refChange)) { LOGGER.info("Deleted a ref that never existed. This shouldn't ever occur."); } else if (isDeleted(refChange) || isCreated(refChange)) { branchCreation(refChange,event.getRepository(),commitList); } else { sepCommits.findCommitInfo(refChange,commitList); } } else { refNotProcessed(refChange); } } return commitList; } 我试图确保如果我有一个git notes commit,则忽略处理并调用refNotProcessed(..). 幸运的是,我能够相对轻松地解决这个问题并得出以下解决方案: @RunWith (MockitoJUnitRunner.class) public class RefChangEventTest { @Mock RefChange ref; @Mock RepositoryRefsChangedEvent refsChangedEvent; @Mock Repository repo; @Mock ApplicationPropertiesService appService; @Mock SEPCommits sepCommits; @Spy SEPRefChangeEventImpl sepRefChangeEvent = new SEPRefChangeEventImpl(sepCommits,appService); @Before public void testSetup() { Collection<RefChange> refList = new ArrayList<RefChange>(1); refList.add(ref); when(refsChangedEvent.getRefChanges()).thenReturn(refList); when(refsChangedEvent.getRepository()).thenReturn(repo); } @Test public void gitNotesAreIgnored() throws Exception { when(ref.getRefId()).thenReturn("refs/notes/foo"); when(ref.getFromHash()).thenReturn("da69d7e202d7f66cba01c6f4030bd5975adbf200"); when(ref.getToHash()).thenReturn("da69d7e202d7f66cba01c6f4030bd5975adbf201"); doNothing().when(sepCommits).findCommitInfo(any(RefChange.class),any(Repository.class),any(ArrayList.class)); sepRefChangeEvent.processEvent(refsChangedEvent); verify(sepRefChangeEvent,times(1)).refNotProcessed(ref); } 在此之后,如果我将ref名称更改为refs / heads / foo之类的内容,我想看看我的单元测试是否会因正确的原因而失败.我希望看到类似的内容:预期1执行refNotProcessed但根本没有运行 相反,我得到: java.lang.NullPointerException at com.cray.stash.SEPRefChangeEventImpl.processEvent(SEPRefChangeEventImpl.java:62) at ut.com.isroot.stash.plugin.RefChangEventTest.gitNotesAreIgnored(RefChangEventTest.java:48) 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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) at org.junit.runners.ParentRunner.run(ParentRunner.java:309) at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37) at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62) at org.junit.runner.JUnitCore.run(JUnitCore.java:160) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:253) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84) 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) 其中指向sepCommits.findCommitInfo(..)的调用默认情况下,当模拟调用时,带有void签名的方法不执行任何操作.这正是我想要它做的.我希望它被调用,但什么也不做,只记录sepCommits与之交互的事实.为什么NPE会发生? 以下是人们要求的更多方法: public SEPRefChangeEventImpl(SEPCommits sepCommits,ApplicationPropertiesService appService) { this.sepCommits = sepCommits; try { endpoint = appService.getPluginProperty("plugin.fedmsg.events.relay.endpoint"); } catch (Exception e) { LOGGER.error("Failed to retrieve propertiesn" + e); } if (endpoint == null) { endpoint = "tcp://some.web.address" } } public void refNotProcessed(RefChange refChange) { LOGGER.info("This type of refChange is not supported.n refId={} fromHash={} toHash={} type={}",refChange.getType()); } public void findCommitInfo(RefChange ref,Repository repo,ArrayList<Message> commitList) { Page<Commit> commits = getChangeset(repo,ref); for (Commit commit : commits.getValues()) { String topic = topicPrefix + repo.getProject().getKey() + "." + repo.getName() + ".commit"; Message message = new Message(getInfo(commit,ref),topic); commitList.add(message); } } 解决方法
从我在您的设置中看到的,sepCommits是类中的依赖项,包含processEvent()方法.
您必须在sepRefChangeEvent变量中注入您在测试中创建的模拟.通常,这可以通过在构造期间将其作为参数传递或通过setter方法来完成.我在你的测试类中看不到这样的代码.我认为你实际上正在击中一个真实的实例,而不是那里的模拟实例,这导致异常. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |