2013-03-09 13 views
12

Ho creato un nuovo progetto di test Android. Ho scaricato powermock-mockito-junit-1-1.5.zip da https://code.google.com/p/powermock/downloads/list. Ho aggiunto tutte le librerie alla cartella libs del progetto di test. La classe di test è un oggetto molto semplice:Come utilizzare PowerMock nei progetti Android?

package com.test.test; 

import org.junit.runner.RunWith; 
import org.powermock.modules.junit4.PowerMockRunner; 

import android.util.Log; 

@RunWith(PowerMockRunner.class) 
public class TestTestAndroid { 

    public void testRuns() { 
     Log.e("test", "Test case is called"); 
    } 
} 

Poi, ho provare a eseguire il progetto da Eclipse, o fare il progetto dalla riga di comando. Ottengo lo stesso errore:

Conversion to Dalvik format failed: Unable to execute dex: Multiple dex files define Lorg/hamcrest/Description;

Come si è visto, sia junit-4.8.2.jar e mockito-all-1.9.5.jar definiscono org.hamcrest.Description. Devo includere il barattolo di Mockito per ovvi motivi: ho bisogno di Mockito. Una versione diversa di JUnit è fornita da Android, ma è una vecchia versione che non include l'annotazione @RunWith.

Qualcuno può rispondere a come utilizzare powermock e mockito in un progetto Android, senza il problema in conflitto org.hamcrest.Description?

risposta

10

Spiacente, non è possibile utilizzare PowerMock nel Dalvik VM.

PowerMock funziona eseguendo il test con un ClassLoader personalizzato che utilizza Javassist per modificare il bytecode delle classi. Funziona bene su una normale JVM, ma su Dalvik il bytecode e il formato della classe sono diversi, quindi questo approccio non funziona. PowerMock avrebbe dovuto essere riscritto per usare Dexmaker invece di Javassist - questo sarebbe decisamente non banale, e non vedo nulla di simile sul PowerMock issues list.

+0

Se non è possibile utilizzare PowerMock su Android, sai un altro modo per bloccare un metodo statico su Android? – lowellk

+5

@lowellk C'è una soluzione alternativa. Avere un metodo non statico chiama il metodo statico, quindi lo stub. Ad esempio, se 'HttpConstants.getUrl()' è un metodo statico, scrivere un altro metodo: 'String getUrl() {return HttpConstants.getUrl(); } 'Quindi, puoi stubare quel metodo. –

+0

+1 per @ suggerimento di MattQuigley –

8

In realtà, trovo che questo sia completamente falso (almeno con l'ultima versione).

Nel mio setup Gradle per il modulo dove voglio testare il mio codice che ho

// Mockito and PowerMock 
androidTestCompile ('org.powermock:powermock-mockito-release-full:1.6.0') { 
    exclude module: 'hamcrest-core' 
    exclude module: 'objenesis' 
} 

e tutto funziona bene. Finché io uso:

@RunWith(PowerMockRunner.class) @PrepareForTest(ClassToMock.class) 

per annotare la mia classe (ad esempio, non può essere eseguito con Robolectric, ancora bene in ambienti CI)

+1

Puoi postare la configurazione completa di gradle? Non riesco a trovare l'importazione per PowerMockRunner.class –

+0

Sfortunatamente, non posso perché è parte dell'applicazione della nostra azienda, ma dovrebbe essere lì, tramite import 'import org.powermock.modules.junit4.PowerMockRunner;' basta assicurarsi se usi AndroidTestCompile, i tuoi test strumentali usando questa importazione sono nella cartella androidTest, ecc. – AllDayAmazing

+0

ok, ma per avere quell'importazione ho bisogno di avere la seguente compilazione in gradle: androidTestCompile 'org.powermock: powermock-module-junit4: 1.6.2 ' Questo mi causa un sacco di problemi come: "Più file dex definiti ..." –