如何使用 zio-test 测试异常情况
How to test an exception case with zio-test
我有以下功能,我想测试一下:
def people(id: Int): RIO[R, People]
此功能 returns 人们如果有一个 id
,resp。如果没有则失败,例如:
IO.fail(ServiceException(s"No People with id $id"))
快乐案例有效,例如:
suite("Get a Person for an ID") (
testM("get Luke Skywalker") {
for {
peopleRef <- Ref.make(Vector(People()))
luke <- Swapi.>.people(1).provide(Test(peopleRef))
} yield assert(luke, equalTo(People()))
},
但是如何测试失败案例呢?我尝试了不同的东西,主要是类型不匹配。这是一个尝试:
testM("get not existing People") {
(for {
peopleRef <- Ref.make(Vector(People()))
failure = Swapi.>.people(2).provide(Test(peopleRef))
} yield assertM(failure, fail(Cause.die(ServiceException(s"No People with id 2")))
}
)
在@adamfraser 的帮助下 ZIO-Chat:
Basically call run on your failing effect and then assert that it is a failure with Assertion.fails.
Or Assertion.dies if it is an unchecked exception.
我想我现在有一个很好的解决方案。
testM("get not existing People") {
for {
peopleRef <- Ref.make(Vector(People()))
failure <- Swapi.>.people(2).provide(Test(peopleRef)).run
} yield assert(
failure,
fails(equalTo(ServiceException("No People with id 2")))
)
}
仍然欢迎其他解决方案。
我想你肯定明白了。对于有类似问题的其他人,我唯一要补充的是您的示例还涉及环境类型,这是一个很好的讨论主题,但在某种程度上独立于如何使用 ZIO 测试来测试效果是否按预期失败。
我在下面提供了一个最小示例,说明如何测试效果是否按预期失败。如上所述,您将对效果调用 run
以获取退出值,然后使用 Assertion.fails
断言效果因检查异常而失败,Assertion.dies
断言效果失败出现未经检查的异常,或 Assertion.interrupted
测试效果是否被中断。
另请注意,您不必使用 include equalTo("fail")
。如果你只关心效果失败,你可以使用 fails(anything)
。如果您正在测试一个效果是否因指定的异常而消失,您可以执行类似 dies(isSubtype[IllegalArgumentException])
.
的操作
希望对您有所帮助!
import zio.test._
import zio.test.Assertion._
import zio.ZIO
object ExampleSpec
extends DefaultRunnableSpec(
suite("ExampleSpec")(
testM("Example of testing for expected failure") {
for {
result <- ZIO.fail("fail")
} yield assert(result, fails(equalTo("fail")))
}
)
)
您还可以翻转错误和结果通道:
import zio.test._
import zio.test.Assertion._
import zio.ZIO
object ExampleSpec
extends DefaultRunnableSpec(
suite("ExampleSpec")(
testM("Example of testing for expected failure") {
for {
result <- ZIO.fail("fail").flip
} yield assert(result, equalTo("fail"))
}
)
)
这是另一个使用 assertM
的紧凑变体:
object ExampleSpec extends DefaultRunnableSpec {
def spec = suite("ExampleSpec")(
testM("Example of testing for expected failure") {
assertM(ZIO.fail("fail").run)(fails(equalTo("fail")))
}
)
}
如果您的错误是可抛出的,则 equalsTo
在针对 运行 效果运行时会失败,因此您必须使用 isSubtype
断言来检查您是否收到正确的错误这有点棘手:
import zio.test._
import zio.test.Assertion._
import zio.ZIO
object ExampleSpec
extends DefaultRunnableSpec(
suite("ExampleSpec")(
testM("Example of testing for expected failure") {
for {
result <- ZIO.fail(new NoSuchElementException).run
} yield assert(result, fails(isSubtype[NoSuchElementException](anything)))
}
)
)
ZIO 2.0有一些变化:
- 使用
exit
代替run
- 使用
test
代替testM
assert
有一个新的柯里化语法 assert(result)(assertion)
import zio.test._
import zio.test.Assertion._
import zio.ZIO
object ExampleSpec extends DefaultRunnableSpec(
suite("ExampleSpec")(
test("Example of testing for expected failure") {
for {
result <- ZIO.fail("failureResult").exit
} yield assert(result)(
fails(equalTo("failureResult"))
)
}
)
)
我有以下功能,我想测试一下:
def people(id: Int): RIO[R, People]
此功能 returns 人们如果有一个 id
,resp。如果没有则失败,例如:
IO.fail(ServiceException(s"No People with id $id"))
快乐案例有效,例如:
suite("Get a Person for an ID") (
testM("get Luke Skywalker") {
for {
peopleRef <- Ref.make(Vector(People()))
luke <- Swapi.>.people(1).provide(Test(peopleRef))
} yield assert(luke, equalTo(People()))
},
但是如何测试失败案例呢?我尝试了不同的东西,主要是类型不匹配。这是一个尝试:
testM("get not existing People") {
(for {
peopleRef <- Ref.make(Vector(People()))
failure = Swapi.>.people(2).provide(Test(peopleRef))
} yield assertM(failure, fail(Cause.die(ServiceException(s"No People with id 2")))
}
)
在@adamfraser 的帮助下 ZIO-Chat:
Basically call run on your failing effect and then assert that it is a failure with Assertion.fails. Or Assertion.dies if it is an unchecked exception.
我想我现在有一个很好的解决方案。
testM("get not existing People") {
for {
peopleRef <- Ref.make(Vector(People()))
failure <- Swapi.>.people(2).provide(Test(peopleRef)).run
} yield assert(
failure,
fails(equalTo(ServiceException("No People with id 2")))
)
}
仍然欢迎其他解决方案。
我想你肯定明白了。对于有类似问题的其他人,我唯一要补充的是您的示例还涉及环境类型,这是一个很好的讨论主题,但在某种程度上独立于如何使用 ZIO 测试来测试效果是否按预期失败。
我在下面提供了一个最小示例,说明如何测试效果是否按预期失败。如上所述,您将对效果调用 run
以获取退出值,然后使用 Assertion.fails
断言效果因检查异常而失败,Assertion.dies
断言效果失败出现未经检查的异常,或 Assertion.interrupted
测试效果是否被中断。
另请注意,您不必使用 include equalTo("fail")
。如果你只关心效果失败,你可以使用 fails(anything)
。如果您正在测试一个效果是否因指定的异常而消失,您可以执行类似 dies(isSubtype[IllegalArgumentException])
.
希望对您有所帮助!
import zio.test._
import zio.test.Assertion._
import zio.ZIO
object ExampleSpec
extends DefaultRunnableSpec(
suite("ExampleSpec")(
testM("Example of testing for expected failure") {
for {
result <- ZIO.fail("fail")
} yield assert(result, fails(equalTo("fail")))
}
)
)
您还可以翻转错误和结果通道:
import zio.test._
import zio.test.Assertion._
import zio.ZIO
object ExampleSpec
extends DefaultRunnableSpec(
suite("ExampleSpec")(
testM("Example of testing for expected failure") {
for {
result <- ZIO.fail("fail").flip
} yield assert(result, equalTo("fail"))
}
)
)
这是另一个使用 assertM
的紧凑变体:
object ExampleSpec extends DefaultRunnableSpec {
def spec = suite("ExampleSpec")(
testM("Example of testing for expected failure") {
assertM(ZIO.fail("fail").run)(fails(equalTo("fail")))
}
)
}
如果您的错误是可抛出的,则 equalsTo
在针对 运行 效果运行时会失败,因此您必须使用 isSubtype
断言来检查您是否收到正确的错误这有点棘手:
import zio.test._
import zio.test.Assertion._
import zio.ZIO
object ExampleSpec
extends DefaultRunnableSpec(
suite("ExampleSpec")(
testM("Example of testing for expected failure") {
for {
result <- ZIO.fail(new NoSuchElementException).run
} yield assert(result, fails(isSubtype[NoSuchElementException](anything)))
}
)
)
ZIO 2.0有一些变化:
- 使用
exit
代替run
- 使用
test
代替testM
assert
有一个新的柯里化语法assert(result)(assertion)
import zio.test._
import zio.test.Assertion._
import zio.ZIO
object ExampleSpec extends DefaultRunnableSpec(
suite("ExampleSpec")(
test("Example of testing for expected failure") {
for {
result <- ZIO.fail("failureResult").exit
} yield assert(result)(
fails(equalTo("failureResult"))
)
}
)
)