2015-08-16 9 views
6

ho questo metodo di produzione:Mockito Uri.parse restituisce sempre null

public boolean onShouldOverrideUrlLoading(String url) { 
    boolean isConsumed = false; 
    if (url.contains("code=")) { 
     Uri uri = Uri.parse(url); 
     String authCode = uri.getQueryParameter("code"); 
     mView.authCodeObtained(authCode); 
     isConsumed = true; 
    } 
    return isConsumed; 
} 

E ho questo metodo di prova Mockito:

@Test 
public void onShouldOverrideUrlLoadingOnAuthCodeObtained(){ 

    String code = "someCode"; 

    boolean isConsumed = mPresenter.onShouldOverrideUrlLoading("http://localhost/?code=" + code); 

    verify(mView, times(1)).authCodeObtained(code); 
    assertEquals(isConsumed, true); 
} 

Ma sembra una volta che viene eseguito il codice e raggiunge Uri. parse (url), ottengo un puntatore nullo. Cosa mi manca? In produzione funziona perfettamente. Solo durante il test, Uri.parse() restituisce null.

Grazie!

+0

Il problema è probabilmente a Uri, probabilmente male inizializzare nell'ambiente di prova. We 'Uri' non esiste nell'SDK Android [' URI'] (https://developer.android.com/reference/java/net/URI.html#create (java.lang.String)). Quindi non sembra una classe spedita, questo potrebbe essere il problema. Niente relativo al mockito. – Brice

+0

@Brice Grazie. Sì, sembrava essere il problema. Dovresti postare questa come risposta. La classe Uri proviene da Android. Quindi Mockito ha qualche difficoltà a lavorare in questo modo. –

+0

fatto :) Spero che questo abbia aiutato. – Brice

risposta

1

Il problema si trova probabilmente nella classe Uri, poiché il codice in fase di test è il codice statico (Uri.parse(...)), Uri probabilmente sta inizializzando male nell'ambiente di test. Nota ci sono due classi di uri nel SDK Android:

Io non sono uno sviluppatore di Android, ma si consiglia di controllare l'ambiente di test.

+0

Come hai risolto esattamente il problema? Come posso avviare correttamente il mio ambiente di test in Android? – Johannes

+0

@ user59442 Non posso risponderti su questo, non sono uno sviluppatore di _ Android. Chiedi invece all'autore della domanda Alon Minski! – Brice

1

Se si utilizza la classe android.net.Uri, allora avete bisogno di eseguire i test con Robolectric (http://robolectric.org) sulla parte superiore del Mockito

11

Alla fine ho usato PowerMock in cima Mockito per deridere la classe Uri. Utilizzare questi dependecies per aggiungerla:

'org.powermock:powermock-api-mockito:1.4.12' 
'org.powermock:powermock-module-junit4:1.6.2' 

Leggi su di esso here.

Consente di simulare metodi statici, metodi privati, classi finali e altro. Nel mio metodo di prova ho usato:

PowerMockito.mockStatic(Uri.class); 
Uri uri = mock(Uri.class); 

PowerMockito.when(Uri.class, "parse", anyString()).thenReturn(uri); 

Questa superato la linea del codice vero e restituito un oggetto Uri deriso in modo che il test potrebbe andare avanti. Assicurarsi di aggiungere:

@RunWith(PowerMockRunner.class) 
@PrepareForTest({Uri.class}) 

come annotazioni sulla parte superiore del nome della classe di test.

L'utilizzo di Robolectric per affrontare questo problema è anche una tecnica valida.

Spero che questo aiuti un po 'cosa.

0

Ho aggirato questo problema utilizzando il corridore di prova Roboelectric.

@RunWith(RobolectricGradleTestRunner::class) 
@Config(constants = BuildConfig::class, sdk = intArrayOf(19)) 
class WeekPageViewModelConverterTests { 
... 
} 
1

Ho avuto un problema simile a fare le prove con android.net.Uri di classe.

Ho risolto il problema spostando il test dalla cartella 'test' a 'androidTest' ed eseguendolo nel dispositivo. Nel dispositivo, la classe Uri si comporta normalmente.

1

Il problema qui è che il file android.jar utilizzato per eseguire i test di unità non contiene alcun codice effettivo. In questo modo android.net.Uri tornerà null per impostazione predefinita e utilizzando

android { 
    // ... 
    testOptions { 
    unitTests.returnDefaultValues = true 
    } 
} 

non risolverà il problema per questo caso, dal momento che il valore di ritorno di default per il metodo ancora null

La soluzione per me è stato quello di utilizzare il plugin Unmock che l'unico scopo è quello di sganciare alcune delle classi/pacchetti da android.jar e dare la piena implementazione per quelli.

In questo caso specifico, è sufficiente aggiungere il frammento a voi build.gradle file di

apply plugin: 'de.mobilej.unmock' 
//... 
unMock { 
    keepStartingWith "android.net.Uri" 
}