【发布时间】:2014-07-15 16:25:55
【问题描述】:
这可能是 RTFM 类型的问题之一,但是,我一生都无法弄清楚如何以适用于 Asp.net WebApi 的方式将任务链接在一起。
具体来说,我正在寻找如何使用DelegatingHandler 来修改控制器处理后的响应(添加额外的标头),并且我正在尝试使用@987654323 对DelegatingHandler 进行单元测试@实例。
第一个模式
[TestMethod]
public void FirstTest()
{
var task = new Task<string>(() => "Foo");
task.ContinueWith(t => "Bar");
task.Start();
Assert.AreEqual("Bar", task.Result);
}
断言失败,因为task.Result 返回"Foo"
第二种模式
[TestMethod]
public void SecondTest()
{
var task = new Task<string>(() => "Foo");
var continueTask = task.ContinueWith(t => "Bar");
continueTask.Start();
Assert.AreEqual("Bar", continueTask.Result);
}
这在 continueTask.Start() 上失败,除了 System.InvalidOperationException: Start may not be called on a continuation task。
第三种模式
[TestMethod]
public void ThirdTest()
{
var task = new Task<string>(() => "Foo");
var continueTask = task.ContinueWith(t => "Bar");
task.Start();
Assert.AreEqual("Bar", continueTask.Result);
}
这个测试按我预期的方式工作,但是我不确定如何让这个模式与 WebAPI 一起工作。
当前实施
public class BasicAuthenticationHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
var task = base.SendAsync(request, cancellationToken);
task.ContinueWith(AddWwwAuthenticateHeaderTask());
return task;
}
private static Func<Task<HttpResponseMessage>, HttpResponseMessage>
AddWwwAuthenticateHeaderTask()
{
return task =>
{
var response = task.Result;
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
response.Headers.WwwAuthenticate.Add(
new AuthenticationHeaderValue("Basic", "realm=\"api\""));
}
return response;
};
}
}
但是,当我从单元测试中调用BasicAuthenticationHandler 时,在Assert 发生之前没有添加我的标头(如果我调试,我注意到标头是在单元测试之后添加的失败)。
[TestMethod]
public void should_give_WWWAuthenticate_header_if_authentication_is_missing()
{
using (var sut = new BasicAuthenticationHandler())
{
sut.InnerHandler = new DelegatingHttpMessageHandler(
() => new HttpResponseMessage(HttpStatusCode.Unauthorized));
using (var invoker = new HttpMessageInvoker(sut))
{
var task = invoker.SendAsync(_requestMessage, CancellationToken.None);
task.Start();
Assert.IsTrue(
task.Result.Headers.WwwAuthenticate.Contains(
new AuthenticationHeaderValue("Basic", "realm=\"api\"")));
}
}
}
如果我更改生产代码以返回延续任务而不是来自 base.SendAsync 的结果,那么我会收到关于在延续任务上调用 Start 的第二个单元测试异常。
我认为我想在我的生产代码中完成第三个单元测试模式,但是我不知道如何编写它。
我该怎么做(在调用断言之前添加标题)?
【问题讨论】:
-
您使用的是哪个 .NET 框架?
-
即使任务已经完成,也会继续运行。你假设这不是导致你开始过于谨慎的行为。没必要。
标签: c# .net asp.net-web-api task-parallel-library async-await