여기서 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)
답변
이것은 나를 위해 일했습니다. 저는 JUnit 만 사용하고 있으며 타사 라이브러리 없이도Log
클래스 를 매우 쉽게 모의 할 수있었습니다 . 내용이 있는 파일을 Log.java
내부에 생성하십시오 app/src/test/java/android/util
.
package 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...
}
답변
이것을 gradle 스크립트에 넣을 수 있습니다.
android {
...
testOptions {
unitTests.returnDefaultValues = true
}
}
그러면 android.jar의 모의 해제 된 메서드가 예외를 throw할지 아니면 기본값을 반환할지 결정합니다.
답변
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
답변
사용 PowerMockito를 :
@RunWith(PowerMockRunner.class)
@PrepareForTest({Log.class})
public class TestsToRun() {
@Test
public void test() {
PowerMockito.mockStatic(Log.class);
}
}
그리고 당신은 갈 수 있습니다. PowerMockito는 상속 된 정적 메서드를 자동으로 모의하지 않으므로 Log를 확장하는 사용자 지정 로깅 클래스를 모의하려면 MyCustomLog.e ()와 같은 호출에 대해 여전히 Log를 모의해야합니다.
답변
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(){
}
}
답변
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
}
답변
나는 목재를 사용하는 것이 좋습니다로깅을 위해 를 .
테스트를 실행할 때 아무것도 기록하지 않지만 Android Log 클래스가 수행하는 방식처럼 불필요하게 테스트가 실패하지는 않습니다. Timber를 사용하면 앱의 디버그 및 프로덕션 빌드를 편리하게 제어 할 수 있습니다.