2015-12-17 14 views
10

複雑な設定のビット。 Robolectric、PowerMockitoルールベースの設定。PowerMockito:モックでのNotAMockException

@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を呼び出そうとするたびにしかし:

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はMockito.verify()の代わりにverify()メソッドを使用していません。何が得られますか?

EDIT:これはいくつかの点で、いくつかの点でより混乱を招くものではありません。

ServiceCallbackBase自体をテストするための別のテストクラスを作成中です。そのクラスからテストを削除すると、これらのテストは合格になります。別のクラスの次のスニペットは上記のテストを失敗させます。

@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); 
    } 
} 
+0

ここに答えがあります:http://stackoverflow.com/questions/29611893/mockito-notamockexception – piotrek1543

+0

あなたはより詳細にする必要があります。問題のポイントは、スタックトレースのクラス名に明示されているように、疑似コードであることです。 'ServiceCallbackBase $$ EnhancerByMockitoWithCGLIB $$ 9acf906b' –

答えて

11

私はあなたの例を構築することはできませんが、私は非常によく似た問題が生じ、この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はなど$$ $$ ServiceCallbackBase EnhancerByMockitoWithCGLIBを比較します。..ロードされました

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

作られたこの簡単な変更:次にRobolectricによってロード同じでPowermock(明らかにその比較ですにおけるfalseを返す)

によって、私は単にこれはライン@PowerMockIgnore..."org.powermock.*"を追加し、テスト作業を行うために管理しました私のテストはうまくいく、と私は本当にあなたも作ることを願っています。

+0

これに対して十分なアップフォートを与えることはできません。なぜ私は知りませんが、それはそれを修正しました。ありがとうございました! –

+0

私はうれしいです。どういたしまして! – fonkap

+1

私は同じ問題を抱えていました。ただし、**各**テストクラスの 'PowerMockIgnore'アノテーションに' 'org.powermock。* ''を追加してください。 – andy9775