0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Logをテストごとにモックするのは大変なので、専用のルールを作ってみた

Posted at

Androidのプロジェクトでユニットテストを書いているときに、テスト対象のメソッドの中でLog.dなどを呼び出していると、以下のようなエラーが出る。

Method e in android.util.Log not mocked. See https://developer.android.com/training/testing/local-tests#mocking-dependencies for details.
java.lang.RuntimeException: Method e in android.util.Log not mocked. See https://developer.android.com/training/testing/local-tests#mocking-dependencies for details.
	at android.util.Log.e(Log.java)

これは、LogクラスがAndroidフレームワークに依存しているため、それをJVM上で動かすときに、モックを作成する必要があるということを意味している。

なので、MockKを使ってモックすることにする。おそらく次のようになるだろう。

@Before
fun setup() {
  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
}

ただ、毎回これをテストごとに書くのはとても面倒。なのでルールとして作成してみた。

import android.util.Log
import io.mockk.every
import io.mockk.mockkStatic
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement

class MockLogRule: TestRule {
    override fun apply(base: Statement, description: Description): Statement {
        return object : Statement() {
            override fun evaluate() {
                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

                try {
                    base.evaluate()
                } catch (e: Throwable) {
                    throw e
                }
            }
        }
    }
}

ルールを作成する際は、必ずTestRuleを継承する必要があることを忘れてはいけない。
そして、applyメソッドをオーバーライドして、Statementを返す必要がある。

実際にテストで使う場合は、次のようになる。

class RepositoryTest {
  ...
  @get:Rule
  val mockLogRule = MockLogRule()

  @Test
  fun xxx_xxx_xxx() = testScope.runTest {
    ...
  }
}

これで、毎回@Beforeでモックを作成する必要がなくなったのでテストを書く際の効率化に繋がったと思う。

参考

0
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?