asp.net-mvc – Request.GetOwinContext在单元测试中返回null – 如何在单元测试中测试OWIN认证?

前端之家收集整理的这篇文章主要介绍了asp.net-mvc – Request.GetOwinContext在单元测试中返回null – 如何在单元测试中测试OWIN认证?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
@H_502_1@我正在尝试单元测试我正在使用OWIN进行身份验证的新WebAPI项目的身份验证,并且我在单元测试上下文中运行它时遇到问题。

这是我的测试方法

[TestMethod]
public void TestRegister()
{
    using (WebApp.Start<Startup>("localhost/myAPI"))
    using (AccountController ac = new AccountController()
        {
            Request = new System.Net.Http.HttpRequestMessage
                (HttpMethod.Post,"http://localhost/myAPI/api/Account/Register")
        })
    {
        var result = ac.Register(new Models.RegisterBindingModel()
        {
            Email = "testemail@testemail.com",Password = "Pass@word1",ConfirmPassword = "Pass@word1"
        }).Result;
        Assert.IsNotNull(result);
    }
}

我得到一个AggregateException获取.Result与以下内部异常:

Result Message: 
Test method myAPI.Tests.Controllers.AccountControllerTest.TestRegister 
    threw exception: 
System.ArgumentNullException: Value cannot be null.
Parameter name: context
Result StackTrace:  
at Microsoft.AspNet.Identity.Owin.OwinContextExtensions
    .GetUserManager[TManager](IOwinContext context)
at myAPI.Controllers.AccountController.get_UserManager()
...

我已经通过调试确认我的启动方法正在被调用调用ConfigurAuth:

public void ConfigureAuth(IAppBuilder app)
{
    HttpConfiguration config = new HttpConfiguration();
    config.MapHttpAttributeRoutes();
    app.UseWebApi(config);

    // Configure the db context and user manager to use a single 
    //  instance per request
    app.CreatePerOwinContext(ApplicationDbContext.Create);
    app.CreatePerOwinContext<ApplicationUserManager>
        (ApplicationUserManager.Create);

    // Enable the application to use a cookie to store information for 
    //  the signed in user
    //  and to use a cookie to temporarily store information about a 
    //  user logging in with a third party login provider
    app.UseCookieAuthentication(new CookieAuthenticationOptions());
    app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

    // Configure the application for OAuth based flow
    PublicClientId = "self";
    OAuthOptions = new OAuthAuthorizationServerOptions
    {
        TokenEndpointPath = new PathString("/Token"),Provider = new ApplicationOAuthProvider(PublicClientId),AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),AllowInsecureHttp = true
    };

    // Enable the application to use bearer tokens to authenticate users
    app.USEOAuthBearerTokens(OAuthOptions);
}

我已经尝试了一些事情,但似乎没有任何工作 – 我永远不会得到OWIN上下文。以下代码测试失败:

// POST api/Account/Register
[AllowAnonymous]
[Route("Register")]
public async Task<IHttpActionResult> Register(RegisterBindingModel model)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    var user = new ApplicationUser() 
       { UserName = model.Email,Email = model.Email };

    IdentityResult result = await UserManager.CreateAsync(user,model.Password);

    if (!result.Succeeded)
    {
        return GetErrorResult(result);
    }

    return Ok();
}

这将调用UserManager属性

public ApplicationUserManager UserManager
{
    get
    {
        return _userManager ?? Request.GetOwinContext()
           .GetUserManager<ApplicationUserManager>();
    }
    private set
    {
        _userManager = value;
    }
}

它失败了:

return _userManager ?? Request.GetOwinContext()
    .GetUserManager<ApplicationUserManager>();

与NullReferenceException – Request.GetOwinContext返回null。

所以我的问题是:我接近这个错了吗?我应该测试JSON响应吗?还是有一个很好的方法来“内部”测试OWIN认证?

解决方法

GetOwinContext调用context.GetOwinEnvironment();
这是
private static IDictionary<string,object> GetOwinEnvironment(this HttpContextBase context)
    {
        return (IDictionary<string,object>) context.Items[HttpContextItemKeys.OwinEnvironmentKey];
    }

和HttpContextItemKeys.OwinEnvironmentKey是一个常量“owin.Environment”
所以如果你在你的httpcontext的项目中添加它,它将会工作。

var request = new HttpRequest("","http://google.com","rUrl=http://www.google.com")
    {
        ContentEncoding = Encoding.UTF8  //UrlDecode needs this to be set
    };

    var ctx = new HttpContext(request,new HttpResponse(new StringWriter()));

    //Session need to be set
    var sessionContainer = new HttpSessionStateContainer("id",new SessionStateItemCollection(),new HttpStaticObjectsCollection(),10,true,HttpCookieMode.AutoDetect,SessionStateMode.InProc,false);
    //this adds aspnet session
    ctx.Items["AspSession"] = typeof(HttpSessionState).GetConstructor(
        BindingFlags.NonPublic | BindingFlags.Instance,null,CallingConventions.Standard,new[] { typeof(HttpSessionStateContainer) },null)
        .Invoke(new object[] { sessionContainer });

    var data = new Dictionary<string,object>()
    {
        {"a","b"} // fake whatever  you need here.
    };

    ctx.Items["owin.Environment"] = data;

猜你在找的asp.Net相关文章