这里Utils.java是我要测试的类,以下是在UtilsTest类中调用的方法。 即使我正在嘲笑Log.e方法,如下所示
@Before
public void setUp() {
when(Log.e(any(String.class),any(String.class))).thenReturn(any(Integer.class));
utils = spy(new Utils());
}
我收到以下异常
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)
答案 0 :(得分:85)
这对我有用。我只使用JUnit而且我能够非常轻松地模拟Log.java
类而没有任何第三方库。只需在app/src/test/java/android/util
内创建一个文件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...
}
,其内容为:
replacement
答案 1 :(得分:26)
您可以将其放入您的gradle脚本中:
android {
...
testOptions {
unitTests.returnDefaultValues = true
}
}
这将决定android.jar中的unmocked方法是否应该抛出异常或返回默认值。
答案 2 :(得分:23)
使用PowerMockito:
@RunWith(PowerMockRunner.class)
@PrepareForTest({Log.class})
public class TestsToRun() {
@Test
public void test() {
PowerMockito.mockStatic(Log.class);
}
}
你很高兴去。请注意,PowerMockito不会自动模拟继承的静态方法,因此如果要模拟扩展Log的自定义日志记录类,则仍必须模拟Log以获取MyCustomLog.e()之类的调用。
答案 3 :(得分:7)
使用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(){
}
}
答案 4 :(得分:4)
如果使用Kotlin,我建议您使用mockk之类的现代库,该库具有对静电和许多其他东西的内置处理。然后,可以这样做:
mockkStatic(Log::class)
every { Log.v(any(), any()) } returns 0
every { Log.d(any(), any()) } returns 0
every { Log.i(any(), any()) } returns 0
every { Log.e(any(), any()) } returns 0
答案 5 :(得分:3)
多亏了@Paglian的回答和@ Miha_x64的评论,我才能够使Kotlin发挥同样的作用。
在app/src/test/java/android/util
中添加以下Log.kt文件
@file:JvmName("Log")
package android.util
fun e(tag: String, msg: String, t: Throwable): Int {
println("ERROR: $tag: $msg")
return 0
}
fun e(tag: String, msg: String): Int {
println("ERROR: $tag: $msg")
return 0
}
fun w(tag: String, msg: String): Int {
println("WARN: $tag: $msg")
return 0
}
// add other functions if required...
请注意,您对Log.xxx的调用应改为调用这些函数。
答案 6 :(得分:2)
Mockito不会模拟静态方法。在顶部使用PowerMockito。 Here就是一个例子。
答案 7 :(得分:2)
使用PowerMock
可以从Android记录器中模拟 Log.i / e / w静态方法。当然,理想情况下,您应该创建一个日志记录界面或外观,并提供一种记录到不同来源的方法。
这是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")
}
}
记住要在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'
}
要模拟Log.println
方法,请使用:
Mockito.`when`(Log.println(anyInt(), any(), any())).then {
println(it.arguments[2] as String)
1
}
答案 8 :(得分:2)
我建议您使用timber进行日志记录。
尽管在运行测试时它不会记录任何内容,但不会像android Log类那样不必要地使测试失败。 Timber使您可以方便地控制应用程序的调试和生产版本。
答案 9 :(得分:0)
另一种解决方案是使用Robolectric。如果您想尝试一下,请检查its setup。
在模块的build.gradle中,添加以下内容
testImplementation "org.robolectric:robolectric:3.8"
android {
testOptions {
unitTests {
includeAndroidResources = true
}
}
}
在你的考试班上,
@RunWith(RobolectricTestRunner.class)
public class SandwichTest {
@Before
public void setUp() {
}
}
答案 10 :(得分:0)
如果您使用的是org.slf4j.Logger,那么只需使用PowerMockito在测试类中模拟Logger即可。
@RunWith(PowerMockRunner.class)
public class MyClassTest {
@Mock
Logger mockedLOG;
...
}
答案 11 :(得分:0)
扩展了kosiara中在 Java 中将 PowerMock 和 Mockito 与 JDK11 结合使用的答案使用android.Log.v
模拟System.out.println
方法以在Android Studio 4.0.1中进行单元测试。
这是Java的完整解决方案:
import android.util.Log;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.mockito.ArgumentMatchers.any;
@RunWith(PowerMockRunner.class)
@PrepareForTest(Log.class)
public class MyLogUnitTest {
@Before
public void setup() {
// mock static Log.v call with System.out.println
PowerMockito.mockStatic(Log.class);
Mockito.when(Log.v(any(), any())).then(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
String TAG = (String) invocation.getArguments()[0];
String msg = (String) invocation.getArguments()[1];
System.out.println(String.format("V/%s: %s", TAG, msg));
return null;
}
});
}
@Test
public void logV() {
Log.v("MainActivity", "onCreate() called!");
}
}
记住要在单元测试所在的模块 build.gradle文件中添加依赖项:
dependencies {
...
/* PowerMock android.Log for OpenJDK11 */
def mockitoVersion = "3.5.7"
def powerMockVersion = "2.0.7"
// optional libs -- Mockito framework
testImplementation "org.mockito:mockito-core:${mockitoVersion}"
// optional libs -- power mock
testImplementation "org.powermock:powermock-module-junit4:${powerMockVersion}"
testImplementation "org.powermock:powermock-api-mockito2:${powerMockVersion}"
testImplementation "org.powermock:powermock-module-junit4-rule:${powerMockVersion}"
testImplementation "org.powermock:powermock-module-junit4-ruleagent:${powerMockVersion}"
}