Mockito+kotlin-allopenプラグインでモックする
Kotlinでテストを書く場合、kotlin-allopenプラグインを使うと簡単にモックできるということですが、ネットに転がってる情報が思いのほか不親切だった(他責)ので個人的まとめ。
結論
プロジェクトレベルbuild.gradle
とappレベルbuild.gradle
に追記し、アノテーションクラスAllOpen.kt
を作る。
// プロジェクトレベルbuild.gradle buildScript { ... dependencies { ... classpath "org.jetbrains.kotlin:kotlin-allopen:${versions.kotlin}" // 追記 } }
// appレベルbuild.gradle ... apply plugin: 'kotlin-allopen' // 追記 ... // android とか dependencies とか // 追記 allOpen { // 次に作るAllOpenアノテーションのパス annotation("<your package>.AllOpen") }
/* <your package>/AllOpen.kt */ // src/main/package/annotationパッケージとか切って配置 package <your package> @Target(AnnotationTarget.CLASS) // ← 書かなくてもおk annotation class AllOpen
あとはモックするクラスに@AllOpen
アノテーションを付与するだけ。
@AllOpen class TargetClass {}
kotlin-allopenとは
つ公式 kotlinlang.org
Kotlinではコンパイル後のクラスに全てfinal修飾子が付くため、Mockitoを使ったユニットテストでモックする場合にエラーを吐く。
Cannot mock/spy class com.your.package.ExampleClass Mockito cannot mock/spy because : - final class
上記で定義したアノテーション@AllOpen
をモック対象のクラスに付与することで、コンパイル後のクラスに強制的にopen
修飾子を付与してくれるとのこと。
リリースビルドではどうするのよ
テストとリリースとで分ける処理をどこかで見たけど埋もれてしまった。←
mock-maker-inlineは?
Androidテスト全書より。
// src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker を作成 mock-maker-inline // この一行だけを記述
なお、MockMakerを利用した方法では前出のAllOpenを使った方法に比べて、かなりパフォーマンス上の不利益があることが報告されています。どちらの方法を選択するかはパフォーマンスと手間との兼ね合いで判断してください。
ということなので、AllOpen
アノテーションを付与する方法を採用しました。