2015-12-17 40 views
10

Bit di una configurazione complicata. Robolectric, configurazione basata su regole PowerMockito.PowerMockito: NotAMockException su un simulato

@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; 
    } 

Dovrebbe essere piuttosto di routine. Ma ogni volta che provo a chiamare verify su uno di questi "callback" casi finti, per esempio:

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); 
    } 

ottengo un errore in questo modo:

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(); 

E 'chiaramente ed evidentemente stato "arricchito" di mockito, e PowerMock non ha un metodo verify() da usare invece di Mockito.verify() ... cosa dà?

EDIT: questo è in qualche modo più e in qualche modo meno confuso.

Sono in procinto di creare un'altra classe di test per testare ServiceCallbackBase stesso. Se rimuovo i test da quella classe, questi test passano. Il seguente frammento di una classe diversa causa il fallimento dei test precedenti.

@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

Qui troverete la risposta: http://stackoverflow.com/questions/29611893/mockito-notamockexception – piotrek1543

+0

Dovrai essere più dettagliato. Il punto della domanda è che * è * un mock, come chiaramente indicato nel nome della classe nella traccia dello stack: 'ServiceCallbackBase $$ EnhancerByMockitoWithCGLIB $$ 9acf906b' –

risposta

11

non riesco a costruire il tuo esempio, ma sono riuscito a scrivere questo Minitest che produce un problema molto simile:

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

(Notare i Mockito.withSettings(), non so perché, ma che fa la fallimento del test)

Stampe:

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! 
    ...... 

bene, questo assolutamente appare come un problema classloading, Mockito è il confronto ServiceCallbackBase $$ EnhancerByMockitoWithCGLIB $$ ecc .. caricato dal Powermock con la stessa caricato da Robolectric (ovviamente restituito false dal fatto che confronto)

Poi, sono riuscito a far funzionare prova semplicemente aggiungendo "org.powermock.*" alla linea @PowerMockIgnore... questo è:

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

Questa semplice modifica fatti il mio test per lavorare, e spero davvero che faccia anche il tuo.

+0

Non posso darti abbastanza voti per questo. Non so perché, ma è stato risolto. Grazie! –

+0

Sono contento. Prego! – fonkap

+1

Ho avuto lo stesso problema e questo è stato risolto se per il momento. Assicurati però di aggiungere '" org.powermock. * "' All'annotazione 'PowerMockIgnore' su ** ogni ** classe di prova – andy9775