Powermock在最终的void方法上意外引发InvalidUseOfMatchersException



我正在对我的Java应用程序进行单元测试。。

我的目标是使用Powermock在BOProcessor类的实例上创建一个间谍。BOProcessor有一个最终的作废方法;我将设置我的间谍程序,以便在调用此方法时抛出异常。在同一个测试中,我也会嘲笑MyDao,但嘲笑这个类很简单。然后,被嘲笑的MyDao将被传递到名为classUnderTest的MyDaoService实例中。然后,我将针对classUnderTest进行断言。

每当我尝试设置上述场景时,当我在间谍上设置doThrow时,Powermock(或Mockito?)会抛出InvalidUseOfMatchersException。奇怪的是,只有当doThrow期望值后面跟着对classUnderTest的调用时,才会抛出此异常。如果我删除稍后调用classUnderTest,那么预期效果良好。更奇怪的是,classUnderTest甚至没有使用抛出错误的间谍!

这是我上面概述的全部测试代码。为了突出这个问题,我删除了所有不直接相关的代码。(我甚至删除了这个测试的全部目的。)

package my.package;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doThrow;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.spy;
import org.junit.Test;
public class WhatAmIDoingWrong {
@Test
public void whatAmIDoingWrong() {
MyDao mockedDao = mock(MyDao.class);
BOProcessor processor = new BOProcessor();
BOProcessor mockedProcessor = spy(processor);
MyDaoService classUnderTest = new MyDaoService(mockedDao);
doThrow(new Exception()).when(mockedProcessor).process(any(FakeBusinessObject.class));
classUnderTest.interactWithDao();
}
}

这是从我的测试代码的doThrow行抛出的异常(具有讽刺意味),我正试图解决它。

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Invalid use of argument matchers!
0 matchers expected, 1 recorded:
-> at my.package.WhatAmIDoingWrong.whatAmIDoingWrong(WhatAmIDoingWrong.java:21)
This exception may occur if matchers are combined with raw values:
//incorrect:
someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(anyObject(), eq("String by matcher"));
For more info see javadoc for Matchers class.
at my.package.MyDaoService.interactWithDao(MyDaoService.java:33)
at my.package.WhatAmIDoingWrong.whatAmIDoingWrong(WhatAmIDoingWrong.java:23)
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.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)

以下是我的测试使用的类。再说一遍,名为classUnderTest的MyDaoService甚至不知道BOProcessor的间谍;它只对MyDao的模拟有效。但是,只有调用classUnderTest时,对BOProcessor spy的期望才会失败。

public class BOProcessor {
public final void process(FakeBusinessObject bar) {}
}
public class FakeBusinessObject {
}
import java.util.Collections;
import java.util.List;
public class MyDao {
public MyDao() {}
public List<String> getAllData(){
return Collections.emptyList();
}
}
public class MyDaoService {
private MyDao applicationDao;
public MyDaoService(MyDao applicationDao) {
this.applicationDao = applicationDao;
}
public synchronized void interactWithDao() {
applicationDao.getAllData();
}
}

我使用JUnit 4.12、Mockito 1.10.19和Powermock 1.7.4。该项目正在运行Spring 4.3.12RELEASE,包括弹簧测试。

为什么Powermock会抛出此异常?我是否未正确使用anyMatcher?为什么只有当稍后的调用与不同的mock交互时才会抛出此异常?

谢谢你的帮助!

事实证明我使用Spies是错误的。org.mockito.stubbing.Stubber.when(T mock)的实现方式意味着我无法按照自己的意愿设定对Spy的期望。但无论如何,Capture实际上更适合我的用例。

最后,我的测试看起来是这样的:

public class FixedNow{
@Test
public void fixedNow() {
MyDao mockedDao = mock(MyDao.class);
BOProcessor mockedProcessor = mock(BOProcessor.class);
FakeBusinessObject problematicBO = new FakeBusinessObject();
ArgumentCaptor<FakeBusinessObject> fakeBOCaptor = ArgumentCaptor.forClass(FakeBusinessObject.class);
MyDaoService classUnderTest = new MyDaoService(mockedDao, mockedProcessor);
doThrow(new Exception()).when(mockedProcessor).process(eq(problematicBO));
doNothing().when(mockedProcessor).process(fakeBOCaptor.capture());
classUnderTest.interactWithDao();
assertThings(BOCaptor.getValue());
}
}

谢谢你的想法!

相关内容

  • 没有找到相关文章

最新更新