模拟每个 {}.throws() 异常未通过测试
mockk every {}.throws() Exception fails test
当先前的方法调用抛出异常时,我需要验证是否未进行特定调用。
// GIVEN
every { relaxedMock.eats() }.throws(NotHungryException())
// WHEN
sut.live()
// THEN
verify (exactly = 0) { relaxedMock2.sleeps() }
这段代码有问题,它失败是因为抛出了异常,而不是因为验证失败。
我知道您的 WHEN 块总是会抛出异常。
在那种情况下,从我的角度来看你有多种选择:
- 简单的普通 Kotlin。用 try-catch 块包裹 WHEN 块,例如像这样:
// 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() }
- 要获得更好的代码,您可以使用 JUnit5 API's Assertions。
assertThrows
将期望特定代码段抛出异常。如果没有抛出异常,它将无法通过测试。它还会return抛出异常,供您检查。
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() }
我遇到了类似的问题,发现我的方法没有被 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
}
}
当先前的方法调用抛出异常时,我需要验证是否未进行特定调用。
// GIVEN
every { relaxedMock.eats() }.throws(NotHungryException())
// WHEN
sut.live()
// THEN
verify (exactly = 0) { relaxedMock2.sleeps() }
这段代码有问题,它失败是因为抛出了异常,而不是因为验证失败。
我知道您的 WHEN 块总是会抛出异常。 在那种情况下,从我的角度来看你有多种选择:
- 简单的普通 Kotlin。用 try-catch 块包裹 WHEN 块,例如像这样:
// 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() }
- 要获得更好的代码,您可以使用 JUnit5 API's Assertions。
assertThrows
将期望特定代码段抛出异常。如果没有抛出异常,它将无法通过测试。它还会return抛出异常,供您检查。
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() }
我遇到了类似的问题,发现我的方法没有被 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
}
}