当前位置:  开发笔记 > Android > 正文

PowerMockito:模拟上的NotAMockException

如何解决《PowerMockito:模拟上的NotAMockException》经验,为你挑选了1个好方法。

有点复杂的设置.Robolectric,PowerMockito基于规则的配置.

@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 setupCallback( boolean hasValidContext, boolean allContextsCanceled ) {
    ServiceCallbackBase 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其中一个"回调"模拟实例时,例如:

  private void test_notifyCallback( boolean isFromCache ) {
    ServiceCallbackBase 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 = new Response<>( new Foo(), new ResponseStatus( 0, "Error" ) );
    uut.handleCallBack( TestEnum.FOO, foo, isFromCache );

    ArgumentCaptor 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()......给出了什么?

编辑:这在某些方面更多,在某些方面不那么令人困惑.

我正在构建另一个测试类来测试ServiceCallbackBase本身.如果我从该类中删除测试,则这些测试通过.不同类中的以下代码段会导致上述测试失败.

@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
public class ServiceCallbackBaseTests {

  @Test
  public void test_nothing(){

  }

  private ServiceCallbackBase uutSpy;


  @Before
  public void setup(){
    uutSpy = mock( ServiceCallbackBase.class );
  }
}

fonkap.. 13

我无法建立你的例子,但我设法写出这个产生非常类似问题的minitest:

@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(),我不知道为什么会让测试失败)

打印:

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正在比较PowerCock加载的ServiceCallbackBase $$ EnhancerByMockitoWithCGLIB $$等与Robolectric加载的相同(显然在该比较中返回false)

然后,我设法让测试工作简单地添加"org.powermock.*"到这一行@PowerMockIgnore...:

@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*", "org.powermock.*"})

这个简单的改变使我的测试工作,我真的希望也能让你的.



1> fonkap..:

我无法建立你的例子,但我设法写出这个产生非常类似问题的minitest:

@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(),我不知道为什么会让测试失败)

打印:

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正在比较PowerCock加载的ServiceCallbackBase $$ EnhancerByMockitoWithCGLIB $$等与Robolectric加载的相同(显然在该比较中返回false)

然后,我设法让测试工作简单地添加"org.powermock.*"到这一行@PowerMockIgnore...:

@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*", "org.powermock.*"})

这个简单的改变使我的测试工作,我真的希望也能让你的.

推荐阅读
吻过彩虹的脸_378
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有