2016-04-22 10 views
17

Tutaj Utils.java jest moją klasą do przetestowania, a następnie jest metodą, która jest wywoływana w klasie UtilsTest. Nawet jeśli jestem szyderczy sposób Log.e jak pokazano poniżejJak pozorować metodę e w Log

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

otrzymuję następujący wyjątek

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) 

Odpowiedz

2

Mockito nie Mock metod statycznych. Użyj PowerMockito na górze. Here jest przykładem.

+1

@ user3762991 Również trzeba zmienić dopasowujących. Nie możesz użyć matchera w instrukcji 'thenReturn (...)'. Musisz określić wartość namacalną. Zobacz więcej informacji [tutaj] (https://stackoverflow.com/questions/36771597/mockito-throwing-invaliduseofweightchercherception) – troig

+0

Jeśli nie można wyśmiać metody e, d, v, to właśnie z powodu tego ograniczenia mockito staje się bezużyteczny? – user3762991

+2

Jeśli nie można zjeść widelca, staje się on bezużyteczny? Ma po prostu inny cel. – Antiohia

17

Korzystanie PowerMockito:

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

i jesteś dobry, aby przejść. Należy pamiętać, że PowerMockito nie będzie automatycznie kpić z odziedziczonych metod statycznych, więc jeśli chcesz sfałszować niestandardową klasę logowania, która rozszerza Log, musisz wciąż kpić z Logu z wywołań takich jak MyCustomLog.e().

+1

Jak otrzymałeś ** PowerMockRunner ** w Gradle? –

+3

@IgorGanapolsky Zobacz moją odpowiedź [tutaj] (http://stackoverflow.com/a/39172168/5495432). –

4

Użyj 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

Można umieścić to w swoim Gradle skryptu:

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

zadecyduje czy unmocked metody z android.jar powinny rzucać wyjątki lub zwracają wartości domyślnych.

+10

* Z Dokumentów: * ** Uwaga: ** Ustawienie właściwości returnDefaultValues ​​na wartość true powinno być wykonywane ostrożnie. Wartości zwracane zer/zero mogą wprowadzać regresje w testach, które są trudne do debugowania i mogą pozwolić przejść testy niepowodzenia. ** Używaj go tylko w ostateczności. ** –

19

To zadziałało dla mnie. Używam tylko JUnit i mogłem bardzo łatwo wykpić klasę Logbez jakiejkolwiek innej biblioteki lib. Wystarczy utworzyć plik Log.java wewnątrz app/src/test/java/android/util o treści:

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

To jest cholernie genialne. I to uchyla potrzebę PowerMockito. 10/10 – Sipty