fresh digitable

めんどくさかったなってことを振り返ったり振り返らなかったりするための記録

JavaとKotlinが混在するプロジェクトでmockitoをmockKで少しずつ置き換えていく

前提

  • 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は念の為書いておく方が良い(少なくともこの例では必須)。