[android] 로그에서 방법 e를 모의하는 방법

여기서 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를 사용하면 앱의 디버그 및 프로덕션 빌드를 편리하게 제어 할 수 있습니다.