2016-04-22 18 views
17

Qui Utils.java è la mia classe da testare e il seguente è il metodo chiamato nella classe UtilsTest. Anche se io sono beffardo metodo Log.e come illustrato di seguitoCome simulare il metodo e nel Registro

@Before 
    public void setUp() { 
    when(Log.e(any(String.class),any(String.class))).thenReturn(any(Integer.class)); 
      utils = spy(new Utils()); 
    } 

Sto ottenendo il seguente eccezione

java.lang.RuntimeException: Method e in android.util.Log not mocked. See http://g.co/androidstudio/not-mocked for details. 
    at android.util.Log.e(Log.java) 
    at com.xxx.demo.utils.UtilsTest.setUp(UtilsTest.java:41) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24) 
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363) 
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137) 
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78) 
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212) 
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) 

risposta

2

Mockito non deridere metodi statici. Usa PowerMockito in cima. Here è un esempio.

+1

@ user3762991 Inoltre è necessario modificare le matchers. Non puoi usare un matcher nell'istruzione 'thenReturn (...)'. Devi specificare un valore tangibile. Vedi maggiori informazioni [qui] (https://stackoverflow.com/questions/36771597/mockito-throwing-invaliduseofmatchersexception) – troig

+0

Se il metodo e, d, v non può essere deriso, solo a causa di questa limitazione il mockito diventa inutilizzabile? – user3762991

+2

Se non riesci a mangiare una forchetta, diventa inutilizzabile? Ha semplicemente un altro scopo. – Antiohia

17

Utilizzando PowerMockito:

@RunWith(PowerMockRunner.class) 
@PrepareForTest({Log.class}) 
public class TestsToRun() { 
    @Test 
    public void test() { 
     PowerMockito.mockStatic(Log.class); 
    } 
} 

E tu sei a posto. Tieni presente che PowerMockito non simulerà automaticamente i metodi statici ereditati, quindi se vuoi prendere in giro una classe di registrazione personalizzata che estende Log, devi comunque prendere in giro Log per chiamate come MyCustomLog.e().

+1

Come hai ottenuto ** PowerMockRunner ** in Gradle ?? –

+3

@IgorGanapolsky Vedi la mia risposta [qui] (http://stackoverflow.com/a/39172168/5495432). –

4

Utilizzare PowerMockito.

@RunWith(PowerMockRunner.class) 
@PrepareForTest({ClassNameOnWhichTestsAreWritten.class , Log.class}) 
public class TestsOnClass() { 
    @Before 
    public void setup() { 
     PowerMockito.mockStatic(Log.class); 
    } 
    @Test 
    public void Test_1(){ 

    } 
    @Test 
    public void Test_2(){ 

    } 
} 
15

Si può mettere questo nello script Gradle:

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

che deciderà se i metodi unmocked da android.jar dovrebbero generare eccezioni o restituire i valori di default.

+10

* Da Documenti: * ** Attenzione: ** L'impostazione della proprietà returnDefaultValues ​​su true dovrebbe essere eseguita con attenzione. I valori di ritorno null/zero possono introdurre regressioni nei test, che sono difficili da debugare e potrebbero consentire il superamento dei test non riusciti. ** Usalo solo come ultima risorsa. ** –

19

Questo ha funzionato per me. Sto solo usando JUnit e sono stato in grado di prendere in giro la classe Logsenza lib di terze parti molto facile. Basta creare un file all'interno Log.javaapp/src/test/java/android/util con contenuti:

public class Log { 
    public static int d(String tag, String msg) { 
     System.out.println("DEBUG: " + tag + ": " + msg); 
     return 0; 
    } 

    public static int i(String tag, String msg) { 
     System.out.println("INFO: " + tag + ": " + msg); 
     return 0; 
    } 

    public static int w(String tag, String msg) { 
     System.out.println("WARN: " + tag + ": " + msg); 
     return 0; 
    } 

    public static int e(String tag, String msg) { 
     System.out.println("ERROR: " + tag + ": " + msg); 
     return 0; 
    } 

    // add other methods if required... 
} 
+0

Questo è dannatamente brillante. E evita la necessità di PowerMockito. 10/10 – Sipty

Problemi correlati