[英]How to mock a method with CancellationToken passed as parameter?
我最近正在学习和使用 Polly 来为我的代码添加弹性,特别是对于超时和重试策略。 但是,我不知道如何使用 polly 对代码进行单元测试。 更具体地说,我不知道如何模拟以 Cancellation Token 作为参数的方法。 下面是我的代码结构
public class Caller
{
private IHttpManager httpManager;
private IAsyncPolicy<HttpResponseMessage> policyWrap;
public Caller(IHttpManager httpManager, IAsyncPolicy<HttpResponseMessage> policyWrap)
{
this.httpManager= httpManager;
this.policyWrap = policyWrap;
}
public async Task CallThirdParty()
{
HttpResponseMessage httpResponse = await policyWrap.ExecuteAsync(async ct => await httpManager.TryCallThirdParty(ct), CancellationToken.None);
}
}
public interface IHttpManager
{
Task<HttpResponseMessage> TryCallThirdParty(CancellationToken cancellationToken);
}
下面是我打算运行但不知道如何运行的单元测试。
[Test]
public void TestBehaviourUnderTimeoutPolicy()
{
// Set up the timeout policy such that the governed delegate will terminate after 1 sec if no response returned
AsyncTimeoutPolicy<HttpResponseMessage> timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(1, TimeoutStrategy.Optimistic);
// mock IHttpManager
var mockHttpManager= new Mock<IHttpManager>();
// THIS IS WHERE I'M HAVING TROUBLE WITH.
// I want to simulate the behaviour of the method such that
// it will throw an exception whenever the CancellationToken passed from the polly caller expires
// But how can I do that with mock?
mockHttpManager.Setup(m => m.TryCallThirdParty(It.IsAny<CancellationToken>()))).Returns(Task.Run(() => { Thread.Sleep(10000); return new HttpResponseMessage(); }));
Caller c = new Caller(mockHttpManager.Object, timeoutPolicy);
await c.CallThirdParty();
}
@Noremac 是对的(您在一个单元测试中测试了 2 个元素)。
但是,要回答“ CancellationToken
时如何使Mock<T>
抛出异常”的问题:使用Returns<TParam1, ...>(Func<TResult, TParam1>)
重载。 为了清楚起见,我用CancellationTokenSource
替换了AsyncTimeoutPolicy
。
// This test will perma-hang if the exception is not thrown
[TestMethod]
[ExpectedException(typeof(OperationCanceledException))]
public async Task TestMethod1()
{
var source = new Mock<IHttpManager>();
source.Setup(s => s.TryCallThirdParty(It.IsAny<CancellationToken>())).Returns<CancellationToken>(
async token =>
{
// Wait until the token is cancelled
await Task.Delay(Timeout.Infinite, token);
});
var tcs = new CancellationTokenSource(1000);
await new Caller().Get(source.Object, tcs.Token);
}
您剪下的代码永远不会调用此方法“c.TryCallThirdParty”。
您是否尝试使用Task.Delay(Timespan.FromSeconds(1))
而不是Thread.Sleep
? 每次都使用 Task.Delay 而不是 Thread.Sleep 更好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.