web-dev-qa-db-ja.com

Logでメソッドeをモックする方法

ここでUtils.Javaはテスト対象のクラスであり、以下はUtilsTestクラスで呼び出されるメソッドです。以下に示すようにLog.eメソッドをock笑していても

 @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)
51
user3762991

これは私のために働いた。私はJUnitのみを使用しており、Logクラスをモックアップできましたサードパーティのライブラリなしで非常に簡単です。ファイルを作成するだけで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...
}
96
Paglian

これをgradleスクリプトに入れることができます:

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

これにより、Android.jarの非モックメソッドが例外をスローするか、デフォルト値を返すかが決まります。

29
IgorGanapolsky

PowerMockito を使用:

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

そして、あなたは行ってもいいです。 PowerMockitoは継承された静的メソッドを自動的にモックしないので、Logを拡張するカスタムロギングクラスをモックしたい場合は、MyCustomLog.e()などの呼び出しのログをモックする必要があります。

24
plátano plomo

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
8
Greg Ennis

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

    }
 }
7
Payal Kothari

ロギングには timber を使用することをお勧めします。

ただし、テストの実行時には何も記録されませんが、テストが不必要に失敗することはありませんが、Android Logクラスのようになります。アプリ。

2
Tosin John

PowerMockを使用すると、モックできますLog.i/e/w静的メソッド from Androidロガー。もちろん理想的にはロギングインターフェイスまたはファサードを作成し、さまざまなソースへのロギング方法を提供する必要があります。

これは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
}

Mockitoは静的メソッドをモックしません。上部のPowerMockitoを使用します。 ここ は例です。

2
Antiohia

別の解決策は、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() {
  }
}

Robolectricの新しいバージョン(4.3でテスト済み)では、テストクラスは次のようになります。

@RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowLog.class)
public class SandwichTest {
    @Before
    public void setUp() {
        ShadowLog.setupLogging();
    }

    // tests ...
}
0
Lipi

Org.slf4j.Loggerを使用している場合、PowerMockitoを使用してテストクラスでLoggerをモックするだけでうまくいきました。

@RunWith(PowerMockRunner.class)
public class MyClassTest {

@Mock
Logger mockedLOG;

...
}
0
user0904