В модульном тестировании при разработке Android-приложений на Kotlin понимание различий между моками и стабами имеет значение. И моки, и стабы — это подтипы тестовых двойников (дублеров), используемых для подмены реальных объектов во время тестирования, но они служат разным целям. Разберемся в их различиях на подробных примерах кода.
Моки:
Моки (mocks, макеты) — это объекты с заранее запрограммированными ожиданиями. Они проверяют взаимодействие между тестовым кодом и объектом, который «подменяется» моком. Моки ожидают определенных вызовов методов с определенными аргументами и возвращаемыми значениями. Моки передают ошибку, если эти ожидания не осуществились во время выполнения теста.
В каких случаях следует использовать моки:
- Тестирование взаимодействий между объектами, в первую очередь вызовы методов.
- Для проверки, что методы вызываются с нужными аргументами и в нужном порядке.
Пример:
Предположим, у нас есть класс UserService
, отвечающий за аутентификацию в Android-приложении:
class UserService { fun authenticate(username: String, password: String): Boolean { // Authenticates user and returns true or false } }
Тестируем аутентификацию с помощью мока UserService
:
import org.junit.Assert.assertTrue import org.junit.Test import org.mockito.Mockito.* class UserServiceTest { @Test fun `test user authentication`() { // Create a mock UserService object val userService = mock(UserService::class.java) // Set up expectations `when`(userService.authenticate("user1", "password123")).thenReturn(true) // Call the method under test val result = userService.authenticate("user1", "password123") // Verify expectations verify(userService).authenticate("user1", "password123") assertTrue(result) } }
Стабы:
Стабы (stubs, заглушки) — это объекты, используемые для предоставления предопределенных ответов на вызовы методов. Они не проверяют взаимодействие, а просто возвращают предопределенные значения при вызове метода с аргументами.
Когда использовать стабы:
- Когда нужно обеспечить предсказуемые ответы на вызовы методов без проверки взаимодействий.
- Когда нужно изолировать тестируемый код от внешних зависимостей.
Пример:
Предположим, у нас есть класс NetworkService
, отвечающий за выполнение сетевых запросов в Android-приложении:
class NetworkService { fun fetchData(): String { // Make a network request and return data } }
Мы хотим протестировать класс, который зависит от NetworkService
, не выполняя сетевых запросов:
class NetworkClient(private val networkService: NetworkService) { fun getData(): String { return networkService.fetchData() } }
Мы создаем стаб NetworkService
, чтобы предоставить предопределенные данные для тестирования:
class StubNetworkService: NetworkService { override fun fetchData(): String { return "Mocked data" } } class NetworkClientTest { @Test fun `test network client with stub`() { // Create a stub NetworkService object val stubNetworkService = StubNetworkService() // Create a NetworkClient instance with the stub val networkClient = NetworkClient(stubNetworkService) // Call the method under test val result = networkClient.getData() // Verify the result assertEquals("Mocked data", result) } }
В приведенных выше примерах моки проверяют, что вызовы методов выполняются с ожидаемыми аргументами и возвращаемыми значениями, в то время как стабы просто предоставляют предопределенные ответы без проверки взаимодействия.
В своих модульных тестах под Android выбирайте моки для тестирования взаимодействий, и стабы для тестирования поведения.
Различия:
Понимание разницы между моками и стабами — фундаментальная вещь для эффективного юнит-тестирования при разработке Android-приложений на Kotlin. Еще раз:
- Моки применяются для верификации взаимодействия между объектами, проверяя, что определенные вызовы методов выполняются с ожидаемыми аргументами и возвращают правильные значения.
- Стабы предоставляют предопределенные ответы на вызовы методов без проверки взаимодействий, что позволяет изолировать тестируемый код от внешних зависимостей.
Освоив нюансы использования моков и стабов, разработчики смогут писать более надежные юнит-тесты, которые надежнее проверяют поведение их Android-приложений. Выбирайте тип дублера по ситуации, в соответствии с особенностями каждого тестового сценария.