Котлин с Мокито

Котлин с Мокито

1. Вступление

Котлин и Ява идут рука об руку. Это означает, что мы можем использовать огромное количество существующих библиотек Java в наших проектах Kotlin.

В этой короткой статье мы увидим, как мы можем имитировать использованиеMockito в Kotlin. Если вы хотите узнать больше о библиотеке,check this article.

2. Настроить

Прежде всего, давайте создадим проектMaven и добавим зависимостиJUnit иMockito вpom.xml:


    org.mockito
    mockito-all
    2.0.2-beta
    test


    junit
    junit
    4.12
    test

Нам также нужно сообщить Maven, что мы работаем с Kotlin, чтобы он скомпилировал для нас исходный код. Посмотритеofficial Kotlin documentation для получения дополнительной информации о том, как настроить это вpom.xml.

3. ИспользованиеMockito сKotlin

Предположим, у нас есть реализация, которую мы хотим протестировать -LendBookManager.. Этот класс имеет зависимость от службы с именемBookService, которая еще не реализована:

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

BookService вводится во время создания экземпляраLendBookManager и используется дважды в методеcheckout, который является методом, для которого нам нужно написать наш тест:

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 пригодится.

Мы можем с помощью всего двух строк кода создать макет интерфейсаBookService и указать ему, чтобы он возвращал фиксированное значение при вызове методаinStock():

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

Это заставит экземплярmockBookService возвращатьtrue всякий раз, когда методinStock() вызывается с аргументом 100 (обратите внимание, что нам пришлось экранировать методwhen(), используя обратную кавычку; это требуется, посколькуwhen - это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)
}

Заметил, что для этого теста мыtoldmockBookService должны возвращатьfalse, когда его спрашивают, есть ли в наличии книга с идентификатором 100. Это должно привести к тому, что вызовcheckout() вызоветIllegalStateException.

Мы используем свойствоexpected в аннотации@Test, указывая на то, что мы ожидаем, что этот тест вызовет исключение.

4. MockitoKotlin Библиотека

Мы можем сделать наш код более похожим на 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(). При использовании этого метода мы можем использовать вывод типа, чтобы мы могли вызывать метод без передачи каких-либо дополнительных параметров.

Наконец, этоlibrary exposes a new whenever() method that can be used freely, without the need for back-ticks like we had to when using Mockito’s native when() method.

Проверьтеtheir wiki для получения полного списка улучшений.

5. Заключение

В этом кратком руководстве мы рассмотрели, как настроить наш проект для совместного использования Mockito и Kotlin, и как мы можем использовать эту комбинацию для создания макетов и написания эффективных модульных тестов.

Как всегда, вы можете ознакомиться с полным исходным кодом вGitHub repo.