#kotlin #mockk
#kotlin #mockk
Вопрос:
Мне нужно убедиться, что определенный вызов не выполняется, когда предыдущий вызов метода вызывает исключение.
// GIVEN
every { relaxedMock.eats() }.throws(NotHungryException())
// WHEN
sut.live()
// THEN
verify (exactly = 0) { relaxedMock2.sleeps() }
Проблема с этим кодом, он завершается с ошибкой из-за исключения, а не из-за неудачной проверки.
Комментарии:
1. Итак
sut.live()
, генерирует исключение, которое не проходит ваш тест?2. Я думаю, вы можете ожидать только, что генерируется определенное исключение. Нет смысла тестировать базовое поведение языка: если что-то брошено — поток методов будет прерван.
3. все, что сказал @standalone, имеет смысл. но если вы все еще хотите попробовать, тогда окружите вызов
live()
с помощью try / catch , а затем вызов verify вне блока try
Ответ №1:
Я понимаю, что ваш блок WHEN всегда будет генерировать исключение. В этом случае у вас есть несколько вариантов, с моей точки зрения:
- Простой обычный Kotlin. Оберните блок WHEN блоком try-catch, например, так:
// GIVEN
every { relaxedMock.eats() }.throws(NotHungryException())
// WHEN
var exceptionThrown: Boolean = false
try {
sut.live()
} catch(exception: NotHungryException) {
// Maybe put some assertions on the exception here.
exceptionThrown = true
}
assertTrue(exceptionThrown)
// THEN
verify (exactly = 0) { relaxedMock2.sleeps() }
- Для более удобного кода вы можете использовать утверждения API JUnit5.
assertThrows
будет ожидать, что исключение генерируется определенным фрагментом кода. Тест завершится неудачно, если исключение не будет выдано. Также он вернет выданное исключение, чтобы вы могли его проверить.
import org.junit.jupiter.api.Assertions
// GIVEN
every { relaxedMock.eats() }.throws(NotHungryException())
// WHEN
val exception = Assertions.assertThrows(NotHungryException::class.java) { sut.live() }
// THEN
verify (exactly = 0) { relaxedMock2.sleeps() }
- Если вы используете Kotest, вы можете использовать
shouldThrow
утверждение. Что также позволяет вам извлекать генерируемое исключение и проверять его тип.
import io.kotest.assertions.throwables.shouldThrow
// GIVEN
every { relaxedMock.eats() }.throws(NotHungryException())
// WHEN
val exception = shouldThrow<NotHungryException> { sut.live() }
// THEN
verify (exactly = 0) { relaxedMock2.sleeps() }
Ответ №2:
У меня была аналогичная проблема, и я обнаружил, что мой метод не окружен try catch . Это означает, что метод всегда будет генерировать исключение.
Тест
Модульный тест для проверки результата при вызове следующего метода при его блокировке с помощью предопределенного исключения
@Test
fun returnSearchError() {
every { searchService.search(query) }.throws(BadSearchException())
val result = searchRepository.search(query)
assertEquals(SearchStates.SearchError, result)
}
Ошибочный код
fun search(query: String): SearchStates {
val result = searchService.search(query) // No try catch for the thrown exception
return try {
SearchStates.MatchingResult(result)
} catch (badSearchException: BadSearchException) {
SearchStates.SearchError
}
}
Переработал его на
fun search(query: String): SearchStates {
return try {
val result = searchService.search(query)
SearchStates.MatchingResult(result)
} catch (badSearchException: BadSearchException) {
SearchStates.SearchError
}
}