Mockitoとコトリン

1前書き

コトリンとジャワは手をつないで歩きます。これは、Kotlinプロジェクトで膨大な数の既存のJavaライブラリを活用できることを意味します。

この短い記事では、Kotlinのhttp://site.mockito.org/[Mockito]を使用してモックする方法を説明します。ライブラリについてもっと知りたい場合は、/mockito-annotations[この記事をチェックしてください。

2セットアップ

まず、https://maven.apache.org/[Maven]プロジェクトを作成し、https://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22junit%22[]を追加しましょう。 __pom.xml内のJUnit]およびhttps://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22org.mockito%22[Mockito]依存関係

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-all</artifactId>
    <version>2.0.2-beta</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

また、私たちはKotlinと協力してソースコードをコンパイルするようにMavenに指示する必要があります。 pom.xml で設定する方法についての詳細はhttps://kotlinlang.org/docs/reference/using-maven.html[Kotlinの公式ドキュメント]をご覧ください。

3. Mockito Kotlin の併用

テストしたい実装があるとします - LendBookManager. このクラスは BookService と呼ばれるサービスに依存していますが、まだ実装されていません。

interface BookService {
    fun inStock(bookId: Int): Boolean
    fun lend(bookId: Int, memberId: Int)
}

BookService は、 LendBookManager のインスタンス化中に注入され、 checkout メソッド全体で2回使用されます。これは、テストを書くために必要なメソッドです。

class LendBookManager(val bookService:BookService) {
    fun checkout(bookId: Int, memberId: Int) {
        if(bookService.inStock(bookId)) {
            bookService.lend(bookId, memberId)
        } else {
            throw IllegalStateException("Book is not available")
        }
    }
}

BookService をモックする能力を持たずにそのメソッドのユニットテストを書くのは難しいでしょう - Mockitoが役に立つところです。

2行のコードで BookService インターフェースのモックを作成し、 inStock() メソッドが呼び出されたときに固定値を返すように指示できます。

val mockBookService = Mockito.mock(BookService::class.java)
Mockito.`when`(mockBookService. inStock(100)).thenReturn(true)

これにより、 inStock() メソッドが引数100で呼び出されるたびに mockBookService インスタンスが true を返すように強制されます(バッククォートを使用して when() メソッドをエスケープする必要があることに注意してください。 Kotlin言語のkotlinlang.org/docs/reference/control-flow.html#when-exex[reserved keyword]。

インスタンス化中にこの擬似インスタンスを LendBookManager に渡し、テストしたいメソッドを呼び出して、操作の結果として lend() メソッドが呼び出されたことを確認できます。

val manager = LendBookManager(mockBookService)
manager.checkout(100, 1)
Mockito.verify(mockBookService).lend(100, 1)

メソッドの実装の他の論理パスをすぐにテストできます。目的の書籍が在庫にない場合は例外がスローされます。

@Test(expected = IllegalStateException::class)
fun whenBookIsNotAvailable__thenAnExceptionIsThrown() {
    val mockBookService = Mockito.mock(BookService::class.java)
    Mockito.`when`(mockBookService. inStock(100)).thenReturn(false)
    val manager = LendBookManager(mockBookService)
    manager.checkout(100, 1)
}

このテストでは、ID 100の書籍が在庫があるかどうかを尋ねられたときに false を返すよう mockBookService told しました。これにより、 checkout()呼び出しで IllegalStateException__がスローされます。

@ Test アノテーションの expected プロパティを使用します。これは、このテストで例外がスローされることを想定していることを示しています。

4 Mockito Kotlin ライブラリ

mockito-kotlin というオープンソースライブラリを使用することで、コードをよりコトリン風に見せることができます。このライブラリは、そのメソッドの周りにMockitoの機能のいくつかをラップし、より単純なAPIを提供します。

@Test
fun whenBookIsAvailable__thenLendMethodIsCalled() {
    val mockBookService : BookService = mock()
    whenever(mockBookService.inStock(100)).thenReturn(true)
    val manager = LendBookManager(mockBookService)
    manager.checkout(100, 1)
    verify(mockBookService).lend(100, 1)
}

また、そのバージョンの mock() メソッドも提供されています。このメソッドを使うとき、型推論を利用することができるので、追加のパラメータを渡さずにメソッドを呼び出すことができます。

最後に、このライブラリは、Mockitoのネイティブの when() メソッドを使用したときのようなバックティックを必要とせずに、自由に使用できる新しい whenever() メソッドを公開します。

機能強化の完全なリストはhttps://github.com/nhaarman/mockito-kotlin/wiki/[their wiki]をチェックしてください。

5結論

このクイックチュートリアルでは、MockitoとKotlinを一緒に使用するようにプロジェクトを設定する方法と、この組み合わせを利用してモックを作成して効果的な単体テストを作成する方法について説明しました。

いつものように、あなたはhttps://github.com/eugenp/tutorials/tree/master/kotlin-libraries[GitHubレポ]で完全なソースをチェックアウトすることができます。