2015-12-17 48 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沒有使用verify()方法而不是Mockito.verify() ...什麼給了?

編輯:這在某些方面更多,並且在某些方面更不易混淆。

我正在建立另一個測試類來測試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 $$等裝通過Powermock與Robolectric加載相同(顯然迴歸在比較假)

然後,我設法讓測試工作簡單地增加"org.powermock.*"到行@PowerMockIgnore...是這樣的:

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

這個簡單的變化作出我的測試工作,我真的希望讓你的工作。

+0

我不能給你足夠的提示。我不知道爲什麼,但是修正了它。謝謝! –

+0

我很高興。別客氣! – fonkap

+1

我遇到了同樣的問題,如果暫時解決了這個問題。請確保你在每個**測試類別 – andy9775

相關問題