我正在尝试对DelegateHandler的一个实现进行单元测试。我的简化实现:
public class FooHandler
: DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
Thread.CurrentPrincipal = new GenericPrincipal(
new GenericIdentity("Vegard"), new[] { "A", "B" });
return await base.SendAsync(request, cancellationToken);
}
}当我尝试对其进行单元测试时,我会这样做:
public class TestHandler : DelegatingHandler
{
private readonly Func<HttpRequestMessage,
CancellationToken, Task<HttpResponseMessage>> _handlerFunc;
public TestHandler()
{
_handlerFunc = (r, c) => Return(HttpStatusCode.OK);
}
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
return _handlerFunc(request, cancellationToken);
}
public static Task<HttpResponseMessage> Return(HttpStatusCode status)
{
return Task.Factory.StartNew(
() => new HttpResponseMessage(status));
}
}
[TestMethod]
public async Task SendAsync_CorrectTokens_IsAuthorized()
{
var message = new HttpRequestMessage(HttpMethod.Get, "http://www.test.com");
var handler = new AuthorizationHeaderHandler
{
InnerHandler = new TestHandler()
};
var invoker = new HttpMessageInvoker(handler);
var result = await invoker.SendAsync(message, new CancellationToken());
Assert.AreEqual(HttpStatusCode.OK, result.StatusCode);
Assert.IsTrue(Thread.CurrentPrincipal.Identity.IsAuthenticated); // fails
Assert.AreEqual("Vegard", Thread.CurrentPrincipal.Identity.Name); // fails
}我猜测这是因为HttpMessageInvoker在单独的线程上运行DelegateHandler。我可以强制它们在同一个线程上吗?
发布于 2013-06-10 21:43:23
我可以强制它们在同一个线程上吗?
你不能这么做。
一个更好的问题是“我如何将Thread.CurrentPrincipal流到正在执行请求的线程”?这个问题有一个答案。
Thread.CurrentPrincipal在ASP.NET中很奇怪,实际上,我建议您根本不要使用它,而是使用HttpContext.User。但如果你愿意,你可以通过理解以下几点来让它工作:
每当线程进入
HttpContext.User请求SynchronizationContext.时,ASP.NET都会传递HttpContext.User覆盖的ASP.NET
不幸的是,您当前的测试在几个关键点上存在缺陷:
Thread.CurrentPrincipal的值是当前运行测试的方式,没有HttpContext (或ASP.NET SynchronizationContext),这会干扰主要用户的流动。要完全测试授权,您需要进行集成测试。
发布于 2013-06-10 21:39:14
您实际遇到的是await的行为。当您退出await时,Await会将主体重置为您进入await时的状态。因此,由于在调用await invoker.SendAsync时没有当前主体,因此在等待调用之后也不会有当前主体。
但是,您的测试处理程序应该看到正确的主体。您可以做的是让您的测试处理程序将当前主体存储在其SendAsync实现中,将其公开为公共属性,然后让您的测试断言测试处理程序看到了它应该看到的主体。这应该可以很好地工作,这应该是您关心的行为。
https://stackoverflow.com/questions/17023682
复制相似问题