前提
- Javaのプロジェクトに徐々にKotlinのコードを増やしていっている
- Javaのテストコードではmockitoを使ってモックオブジェクトを作成していた
- テスト対象のクラスに注入するクラスがKotlinに変わった
- Kotlinのクラスはmockitoではそのままモックできないのでなんかやる必要がある
- mockitoの設定をなんかやるよりはmockKを入れてテストコードをKotlinにする方を頑張ったほうがよさそうと判断して、テストコードをKotlinにすることにした
- JUnit5やSpek2の時代が来そうなのでその前に書いて供養したかった
方針
- かといってテストクラスを全部書き換えるのは大変
- 書き換えたいのはモックを作るところだけ
- モックを作る処理を抽象化して、テストクラスからはどんなモックライブラリを使っているのか意識しなくてもよいようにしてしまう
- テスト対象の生成は
TestRule
の中で行なっており、そこでモックも一緒に作成していたので、TestRule
をそのままモックライブラリのラッパーとして使うことにしたTestRule
のプロパティにアクセスできる別のPageObject的なクラスに移譲しても良かったかも
どうやったか
- テストクラスの静的な内部クラスとして実装していた
TestRule
だけをktファイルに移動させてKotlin化 - mockitoをmockKに置き換え
verify
とかのモック用アサーションをTestRule
クラスに移行して、さらにmockKに置き換え- モックの生成を一回だけにしたかったら
companion object
の中で生成するといいかも。その場合はfinished
とかで忘れずにclearMocks()
をやる
- モックの生成を一回だけにしたかったら
- 公式にTruthを入れる動きがあるのでアサーションライブラリのクラスも隠蔽しておくといいかも
- インターフェイスはあんまり変わらないっぽいのでどっちでいいかも
おまけ
- こんな感じにするとほぼすべての行が
rule.
から始まったりしてテストコードとしては何となく微妙 - Kotlinのテストクラスなら
with(rule) {}
で消せる
これが
fun test() { // setup rule.setupHoge(args = 42, returns = true) // exercise rule.testTarget.hoge(42) // verify rule.verifyHogeRepositoryIsCalled(args = 42) assertThat(rule.testTarget.isVisibleHoge.get()).isTrue() }
こう
@Test fun test(): Unit = with(rule) { // setup setupHoge(args = 42, returns = true) // exercise testTarget.hoge(42) // verify verifyHogeRepositoryIsCalled(args = 42) assertThat(testTarget.isVisibleHoge.get()).isTrue() }
(2019/4/2 修正)
IDEのラベルが荒ぶるので戻り値を書いている。 Unit
を返すメソッドじゃないとテストが実行できないようなので、: Unit
は念の為書いておく方が良い(少なくともこの例では必須)。