Найти тему

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

Оглавление

1. Введение

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

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

2. Настройка

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

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.3.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

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

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

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

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

Служба Book вводится во время создания экземпляра LendBookManager и используется дважды в методе оформления заказа, для которого нам нужно написать наш тест:

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.

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

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

Это заставит экземпляр mockBookService возвращать значение true всякий раз, когда вызывается метод InStock() с аргументом 100 (обратите внимание, что нам пришлось экранировать метод when(), используя обратный флажок; это необходимо, поскольку when является зарезервированным ключевым словом в языке Kotlin).

Затем мы можем передать имитируемый экземпляр в 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)
}

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

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

4. Библиотека Mockito Kotlin

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

Наконец, эта библиотека предоставляет новый метод whenever(), который можно использовать свободно, без необходимости в обратных тиках, как это было при использовании собственного метода when() Mockito.

Ознакомьтесь с их wiki для получения полного списка улучшений.

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

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

Оригинал статьи: https://www.baeldung.com/kotlin/mockito