ここで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)
これは私のために働いた。私は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...
}
これをgradleスクリプトに入れることができます:
Android {
...
testOptions {
unitTests.returnDefaultValues = true
}
}
これにより、Android.jarの非モックメソッドが例外をスローするか、デフォルト値を返すかが決まります。
PowerMockito を使用:
@RunWith(PowerMockRunner.class)
@PrepareForTest({Log.class})
public class TestsToRun() {
@Test
public void test() {
PowerMockito.mockStatic(Log.class);
}
}
そして、あなたは行ってもいいです。 PowerMockitoは継承された静的メソッドを自動的にモックしないので、Logを拡張するカスタムロギングクラスをモックしたい場合は、MyCustomLog.e()などの呼び出しのログをモックする必要があります。
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({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(){
}
}
ロギングには timber を使用することをお勧めします。
ただし、テストの実行時には何も記録されませんが、テストが不必要に失敗することはありませんが、Android Logクラスのようになります。アプリ。
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を使用します。 ここ は例です。
別の解決策は、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 ...
}
Org.slf4j.Loggerを使用している場合、PowerMockitoを使用してテストクラスでLoggerをモックするだけでうまくいきました。
@RunWith(PowerMockRunner.class)
public class MyClassTest {
@Mock
Logger mockedLOG;
...
}