使用自定义授权测试异步Web api方法

时间:2013-10-17 13:09:17

标签: asp.net-web-api nunit authorization resharper async-await

我的WebApi方法或多或少看起来像这样:

public async Task<HttpResponseMessage> Get(Guid id)
{
    var foo = await Store.GetFooAsync(id);
    if (foo.BelongsTo != User.Identity.Name)
        throw new HttpResponseException(HttpStatusCode.Forbidden);
    //return foo here
}

这似乎在实际应用程序中正常工作,其中自定义IHttpModule设置HttpContext.UserThread.CurrentPrincipal中的主体。

但是,从单元测试中调用时:

Thread.CurrentPrincipal = principal;
var response = controller.Get(id).Result;
{p} Userawait之后重置(即继续),因此测试失败。在R#8下运行时会发生这种情况,R#7没有发生这种情况。

我的解决方法是在第一次等待之前保存当前主体,但这只是满足测试运行者需求的黑客攻击。

如何调用我的控制器方法并确保continuation与原始调用具有相同的主体?

2 个答案:

答案 0 :(得分:1)

我通过升级MVC包修复了这个问题。新版本将主体保留在ApiController.RequestContext.Principal中,与Thread.CurrentPrincipal分开,完全避免了问题。

我的新测试代码以:

开头
controller.RequestContext.Principal = principal;

答案 1 :(得分:0)

简短版本是,使用HttpContext.Current.Use而不是Thread.Principal。

简短版本是,使用Request.LogonUserIdentityRequest.RequestContext。HttpContext.User。

async/await保留原始请求上下文,而不是启动该方法的线程。这会产生感觉,否则ASP.NET必须冻结线程并在await返回时使其可用。在await之后运行的线程是来自ThreadPool的线程,因此修改其CurrentPrincipal是一个非常糟糕的主意。

查看Scott Hanselman的播客“transcript”中的Everything .NET programmers know about Asynchronous Programming is wrong了解详情。