第一次重复后测试就挂起
test("test retry exponential") {
for {
_ <- TestClock.adjust(10.milliseconds)
res <- ZIO.fail("fail").retry(Schedule.exponential(10.milliseconds) &&
Schedule.recurs(3).tapOutput(o => ZIO.logInfo(s"retrying $o")))
} yield assertTrue(res == null)
}
当我仅使用 Schedule.recurs 时它可以工作
TestClock 不会提前时间,除非你告诉它。 这里是关于如何提前测试时间的文档。
Schedule.recurs 没有时间部分,它只执行 3 次。 intersection 组合器的工作原理与布尔表达式相同。如果两个计划都准备好再次运行,则合并的计划就准备好运行。如果左或右时间表尚未准备好,则合并的时间表尚未准备好。由于您的测试当前不会提前时间,因此效果第一次失败后永远不会过去 10 毫秒,因此该计划将永远无法准备好再次运行。
作为旁注,这个断言:
test("should fail") {
for {
res <- ZIO.fail("BOOM!")
} yield ??? // assert that effect failed
}
...更好地表达如下:
test("should fail") {
for {
exit <- ZIO.fail("BOOM!").exit
} yield assert(exit)(Assertion.fails(Assertion.equalTo("BOOM!"))
}
为了测试失败,需要调用效果的退出方法。这为您提供了一个 Exit,它有点像具有成功或失败值的 Either,您可以在测试中检查并断言它。
assert 方法采用第一个参数列表中的值,第二个参数列表采用 Assertion[T],其中 T 是值的类型。如您所见,您可以编写这些断言。 Assertion.fails 采用一个新的 Assertion[T],其中 T 现在是效果失败的值,在我们的例子中是字符串,在另一个测试用例中可能是 Throwable。
有时我们不想测试每一个细节,所以有像 Assertion.anything 这样的断言。 Assertion.fails(Assertion.anything) 可能足以满足您的特定情况。还有一种称为assertCompletes,它是典型虚拟断言(如assert true == true)的一种更具描述性的方式。
阅读更多这里。