当我创建一个常规模拟(即通过调用PowerMock.createMock()
)时,我试图弄清楚为什么我可以在模拟对象上成功建立方法调用期望(使用PowerMock),但是我撕裂了我的头发,但是不是当我使用partialMock(通过调用PowerMock.createPartialMock()
)并添加要被模拟的方法时。
下面的代码显示了两个测试(我在这里没有声明任何内容,只是演示了失败)。
第一个运行没有错误。 第二个与第一个完全一样,除了我创建一个局部模拟。
第二次测试引发Assertion
错误(帖子底部的错误文本)声称对Bluetooth.getName()
发出了意外的方法调用,好像我没有正确设置期望值。但我使用与第一次测试中相同的期望设置!
我对Partial Mocks有点新鲜,所以也许我错过了一些东西,但我根据PowerMock的文档和我所做的众多例子设置了我的代码。审查了。
请注意,我尝试模拟的类是Android BluetoothDevice类。它是final
类(这就是我使用PowerMock的原因)。我不确定这是否重要(并且无法想象为什么这会适用于正常的模拟而不是部分模拟),但我想我会提到它以防万一。
public class PartialMockTests
{
@Test
public void testNormalMock()
{
BluetoothDevice normalMock = PowerMock.createMock(BluetoothDevice.class);
// tell EasyMock to expect call to mocked getAddress()
EasyMock.expect(normalMock.getName()).andReturn("fakeName");
EasyMock.expectLastCall().anyTimes();
EasyMock.replay(normalMock);
//Exercise the mock
normalMock.getName(); // No error here!
EasyMock.verify(normalMock);
}
@Test
public void testPartialMock()
{
BluetoothDevice partialMock =
PowerMock.createPartialMock(
BluetoothDevice.class,
"getName", "toString"); //If I don't mock "toString", I get a NPE
// tell EasyMock to expect call to mocked getAddress()
EasyMock.expect(partialMock.getName()).andReturn("fakeName");
EasyMock.expectLastCall().anyTimes();
EasyMock.replay(partialMock);
//Exercise the mock
partialMock.getName(); // Now I get a Assertion Error: Unexpected Method Call! Why?
EasyMock.verify(partialMock);
}
}
这是断言错误文本:
java.lang.AssertionError:意外的方法调用 BluetoothDevice.getName():at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:44) 在 org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:94) 在 org.easymock.internal.ClassProxyFactory $ MockMethodInterceptor.intercept(ClassProxyFactory.java:97) 在 android.bluetooth.BluetoothDevice $$ EnhancerByCGLIB $$ 6c62bd71.getName() 在 my.domain.package.PartialMockTests.testPartialMock(PartialMockTests.java:40) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 org.junit.runners.model.FrameworkMethod $ 1.runReflectiveCall(FrameworkMethod.java:50) 在 org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 在 org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 在 org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 在org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) 在 org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) 在org.junit.runners.ParentRunner $ 3.run(ParentRunner.java:290)at at org.junit.runners.ParentRunner $ 1.schedule(ParentRunner.java:71)at at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)at at org.junit.runners.ParentRunner.access $ 000(ParentRunner.java:58)at at org.junit.runners.ParentRunner $ 2.evaluate(ParentRunner.java:268)at at org.junit.runners.ParentRunner.run(ParentRunner.java:363)at at org.junit.runner.JUnitCore.run(JUnitCore.java:137)at at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78) 在 com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212) 在 com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)