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 ().