PowerMockito:模拟上的NotAMockException [英] PowerMockito: NotAMockException on a mock
问题描述
有点复杂的设置。 Robolectric,PowerMockito基于规则的配置。
Bit of a complicated setup. Robolectric, PowerMockito rule-based config.
@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
// Using "PrepareOnlyThis" prevents powermock from trying to instrument the whole hierarchy,
// part of which we've ignored (android.os.* in this case)
@PrepareOnlyThisForTest({ServiceCallbackBase.class}) // this class extends Handler,
// so we need PrepareOnlyThis. It also has some final methods we need to verify()
public class ServiceBaseTests {
private class Foo {
// nothing
}
@Rule
public PowerMockRule rule = new PowerMockRule();
private ServiceCallbackBase<Object, Foo> setupCallback( boolean hasValidContext, boolean allContextsCanceled ) {
ServiceCallbackBase<Object, Foo> callback = PowerMockito.mock( ServiceCallbackBase.class );
// EDIT: I have converted these to PowerMockito.doReturn()s to no avail.
PowerMockito.when( callback.hasValidContext() ).thenReturn( hasValidContext );
PowerMockito.when( callback.allContextsAreCanceled( any( Message.class ) ) ).thenReturn( allContextsCanceled );
PowerMockito.doNothing().when( callback ).preSendMessage( any( Message.class ) );
return callback;
}
应该很常规。但是,每当我尝试在这些回调模拟实例之一上调用 verify
时,例如:
Should be pretty routine. But whenever I try to call verify
on one of these "callback" mock instances, for instance:
private void test_notifyCallback( boolean isFromCache ) {
ServiceCallbackBase<Object, Foo> callback = setupCallback( true, false );
uut.addHandler( TestEnum.FOO, callback );
uut.addHandler( TestEnum.BAR, PowerMockito.mock( ServiceCallbackBase.class ) );
uut.addHandler( TestEnum.BAZ, PowerMockito.mock( ServiceCallbackBase.class ) );
Response<Foo> foo = new Response<>( new Foo(), new ResponseStatus( 0, "Error" ) );
uut.handleCallBack( TestEnum.FOO, foo, isFromCache );
ArgumentCaptor<Message> captor = ArgumentCaptor.forClass( Message.class );
// this line throws the error.
verify( callback ).preSendMessage( captor.capture() );
assertThat( captor.getValue().what ).isEqualTo( TestEnum.FOO.ordinal() );
assertThat( captor.getValue().obj ).isEqualTo( foo );
assertThat( captor.getValue().arg1 ).isEqualTo( isFromCache ? 1 : 0 );
}
我收到这样的错误:
org.mockito.exceptions.misusing.NotAMockException:
Argument passed to verify() is of type ServiceCallbackBase$$EnhancerByMockitoWithCGLIB$$9acf906b and is not a mock!
Make sure you place the parenthesis correctly!
See the examples of correct verifications:
verify(mock).someMethod();
verify(mock, times(10)).someMethod();
verify(mock, atLeastOnce()).someMethod();
mockito显然很明显地增强了,而PowerMock没有verify()代替 Mockito.verify()
...使用的方法是什么?
It's clearly and obviously been "enhanced" by mockito, and PowerMock doesn't have a verify() method to use instead of Mockito.verify()
... what gives?
EDIT :从某种程度上来说,这更加令人困惑。
EDIT: this is in some ways more and in some ways less confusing.
我正在构建另一个测试类来测试ServiceCallbackBase本身。如果我从该类中删除测试,则这些测试通过。不同类别中的以下代码片段导致上述测试失败。
I'm in the process of building another test class to test ServiceCallbackBase itself. If I remove the tests from that class, these tests pass. The following snippet in a different class causes the tests above to fail.
@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
public class ServiceCallbackBaseTests {
@Test
public void test_nothing(){
}
private ServiceCallbackBase<Object, String> uutSpy;
@Before
public void setup(){
uutSpy = mock( ServiceCallbackBase.class );
}
}
推荐答案
I无法建立您的示例,但我设法编写了一个导致非常相似问题的小型测试:
I cannot build your example, but I managed to write this minitest that produces a very similar problem:
@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
@PrepareOnlyThisForTest({ServiceCallbackBase.class, Dummy.class})
public class MainActivityTest {
@Rule
public PowerMockRule rule = new PowerMockRule();
@Test
public void test1() throws Exception {
try {
//This Mockito.withSettings() thing is important to make the test fail!
ServiceCallbackBase callback = PowerMockito.mock( ServiceCallbackBase.class, Mockito.withSettings());
callback.dispatchMessage(null);
Mockito.verify(callback).dispatchMessage(null);
} catch (Exception e){
e.printStackTrace();
Assert.fail();
}
}
}
(请注意Mockito.withSettings (),我不知道为什么,但这会使测试失败)
(Note the Mockito.withSettings(), I don't know why but that makes the test to fail)
打印:
org.mockito.exceptions.misusing.NotAMockException:
Argument passed to verify() is of type ServiceCallbackBase$$EnhancerByMockitoWithCGLIB$$62776c54 and is not a mock!
Make sure you place the parenthesis correctly!
......
好吧,这绝对是一个类加载问题,mockito正在将Powermock加载的ServiceCallbackBase $$ EnhancerByMockitoWithCGLIB $$ etc ..与Robolectric加载的ServiceCallbackBase $$ EnhancerByMockitoWithCGLIB $$ ..(显然,在该比较中返回false)
Well, this absolutely looks as a classloading issue, mockito is comparing ServiceCallbackBase$$EnhancerByMockitoWithCGLIB$$etc.. loaded by Powermock with the same loaded by Robolectric (obviously returning false in that comparision)
然后,我设法使测试工作只需将 org.powermock。*
添加到 @PowerMockIgnore ...
行,这是:
Then, I managed to make the test work simply adding "org.powermock.*"
to the line @PowerMockIgnore...
this is:
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*", "org.powermock.*"})
这个简单的更改使我的测试生效了,我真的希望也是你的。
This simple change made my test to work, and I really hope that make yours too.
这篇关于PowerMockito:模拟上的NotAMockException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!