注意:这里的测试是为了演示 NSubstitute 的行为。在实际测试中,我们不会测试替代品。 :)
测试重试的一种方法是存根多次返回(如果您需要条件而不是针对特定数量的调用失败,这可能不适用于您的情况,但我认为我会从最简单的方法开始):
[Test]
public void StubMultipleCalls() {
Func<string> throwEx = () => { throw new Exception(); };
var sub = Substitute.For<IThingoe>();
// Stub method to fail twice, then return valid data
sub.MethodToRetry(Arg.Any<string>())
.Returns(x => throwEx(), x => throwEx(), x => "works now");
// The substitute will then act like this:
Assert.Throws<Exception>(() => sub.MethodToRetry(""));
Assert.Throws<Exception>(() => sub.MethodToRetry(""));
Assert.AreEqual("works now", sub.MethodToRetry(""));
// Will continue returning last stubbed value...
Assert.AreEqual("works now", sub.MethodToRetry(""));
Assert.AreEqual("works now", sub.MethodToRetry(""));
}
另一种选择是在对调用进行存根时放入条件:
[Test]
public void StubWithCondition() {
var shouldThrow = true;
var sub = Substitute.For<IThingoe>();
sub.MethodToRetry(Arg.Any<string>()).Returns(x => {
if (shouldThrow) {
throw new Exception();
}
return "works now";
});
Assert.Throws<Exception>(() => sub.MethodToRetry(""));
shouldThrow = false; // <-- can alter behaviour by modifying this variable
Assert.AreEqual("works now", sub.MethodToRetry(""));
}
作为此方法的修改版本,您还可以替换用于存根的回调:
[Test]
public void ReplaceLambda() {
Func<string> methodToRetry = () => { throw new Exception(); };
var sub = Substitute.For<IThingoe>();
sub.MethodToRetry(Arg.Any<string>()).Returns(x => methodToRetry());
Assert.Throws<Exception>(() => sub.MethodToRetry(""));
methodToRetry = () => "works now";
Assert.AreEqual("works now", sub.MethodToRetry(""));
}
理想情况下,我们会尽量避免测试中依赖于时间的逻辑,但如果确实有必要,我们可以在 5 秒后更新第二个示例中的条件,以获得您问题中提到的行为。