studio docs android junit mockito

android - docs - Cómo burlarse del método e en Log



mockito maven (8)

Aquí Utils.java es mi clase para ser probada y el siguiente es el método que se llama en la clase UtilsTest. Incluso si me estoy burlando del método Log.e como se muestra a continuación

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

Estoy recibiendo la siguiente excepción

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)


El uso de PowerMock puede simular los métodos estáticos Log.i / e / w del registrador de Android. Por supuesto, lo ideal sería crear una interfaz de registro o una fachada y proporcionar una forma de registro a diferentes fuentes.

Esta es una solución completa en Kotlin:

import org.powermock.modules.junit4.PowerMockRunner import org.powermock.api.mockito.PowerMockito import org.powermock.core.classloader.annotations.PrepareForTest /** * Logger Unit tests */ @RunWith(PowerMockRunner::class) @PrepareForTest(Log::class) class McLogTest { @Before fun beforeTest() { PowerMockito.mockStatic(Log::class.java) Mockito.`when`(Log.i(any(), any())).then { println(it.arguments[1] as String) 1 } } @Test fun logInfo() { Log.i("TAG1,", "This is a samle info log content -> 123") } }

Recuerda agregar dependencias en gradle:

dependencies { testImplementation "junit:junit:4.12" testImplementation "org.mockito:mockito-core:2.15.0" testImplementation "io.kotlintest:kotlintest:2.0.7" testImplementation ''org.powermock:powermock-module-junit4-rule:2.0.0-beta.5'' testImplementation ''org.powermock:powermock-core:2.0.0-beta.5'' testImplementation ''org.powermock:powermock-module-junit4:2.0.0-beta.5'' testImplementation ''org.powermock:powermock-api-mockito2:2.0.0-beta.5'' }

Para Log.println método Log.println use:

Mockito.`when`(Log.println(anyInt(), any(), any())).then { println(it.arguments[2] as String) 1 }


Esto funcionó para mí. Solo estoy usando JUnit y pude simular la clase Log sin una biblioteca de terceros muy fácil. Simplemente cree un archivo Log.java dentro de la app/src/test/java/android/util con contenido:

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


Mockito no se burla de los métodos estáticos. Usa PowerMockito en la parte superior. Here hay un ejemplo.


Otra solución es utilizar Robolectric. Si quieres probarlo, comprueba su configuración .

En el build.gradle de su módulo, agregue lo siguiente

testImplementation "org.robolectric:robolectric:3.8" android { testOptions { unitTests { includeAndroidResources = true } } }

Y en tu clase de prueba,

@RunWith(RobolectricTestRunner.class) public class SandwichTest { @Before public void setUp() { } }


Puedes poner esto en tu script de Gradle:

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

Eso decidirá si los métodos no simulados de android.jar deberían generar excepciones o devolver valores predeterminados.


Recomendaría el uso de timber para su registro.

Aunque no registrará nada al ejecutar pruebas, pero no falla sus pruebas innecesariamente como lo hace la clase de registro de Android. Timber le brinda un control conveniente tanto de la depuración como de la creación de producción de su aplicación.


Utilice 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(){ } }


Utilizando PowerMockito :

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

Y eres bueno para irte. Tenga en cuenta que PowerMockito no simulará automáticamente los métodos estáticos heredados, por lo que si desea simular una clase de registro personalizada que amplía el Registro, todavía debe simular el Registro para llamadas como MyCustomLog.e ().