调用 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 中包含更多详细信息和代码示例。
我在我的一个项目中使用了稍微过时的 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 中包含更多详细信息和代码示例。