调用 Execute() 时抛出异常的 Polly 策略

Polly policy to throw an exception when Execute() is called

我在我的一个项目中使用了稍微过时的 Polly 版本 - 5.9

对于测试用例,我正在尝试创建一个策略,当对其调用 Execute() 时,该策略将始终抛出异常。此策略将在测试时注入到实际代码中,预计会失败。

我可以这样做:

Policy somePolicy = Policy.Handle<Exception>().Retry();
somePolicy.Execute((cToken) => { throw new Exception(); }, new Context("A context"), cancellationToken); 

但是,我无法访问或控制 Execute() 的第一个参数,即 (cToken) => { throw new Exception(); } 部分。

我也尝试过使用 HandleResult() 的解决方法,如下所示:

Policy<bool> somePolicy = Policy.HandleResult<bool>((o) => { throw new Exception(); }).Retry();

这是有效的,但是,Policy<bool> 使得与仅使用 Policy.

的其余代码集成起来很麻烦

策略本身并不重要,只要它在 Execute() 的任何调用中抛出异常即可。 有实现此目标的干净方法吗?

PS:目前无法升级 Polly。

两个选项:

1 使用 Simmy

Simmy 是一个提供用于注入故障的 Polly 策略的项目。

例如,您可以定义:

var faultPolicy = MonkeyPolicy.InjectFault(new FooException());

(以及许多其他更强大的变体)。

但是,这仅与 Polly v7+ 兼容。

2 使用策略接口和模拟策略

所有 Polly 政策 fulfil execution interfaces。取决于政策:

  • ISyncPolicy
  • ISyncPolicy<TResult>
  • IAsyncPolicy
  • IAsyncPolicy<TResult>

这些接口定义了策略上可用的 .Execute/Async() 重载。

有了这些,您就可以使用标准的依赖注入和模拟技术来构建测试:

  • 在您的生产代码中,按执行接口类型声明和使用策略。
  • 确保将 ISyncPolicy 或类似(或 PolicyRegistry)注入到被测系统中,而不是在其中创建,以便测试可以替代模拟。
  • 在单元测试中,改为传入 Mock<ISyncPolicy>。然后,您可以使用 Moq 等任何模拟工具通过策略模拟 .Execute() 调用以抛出异常。

例如:

ISyncPolicy mockPolicy = new Mock<ISyncPolicy>();
mockPolicy.Setup(p => p.Execute(It.IsAny<Func<Bar>>())
    .Throws(new FooException());

Polly wiki on unit-testing 中包含更多详细信息和代码示例。