Request.GetOwinContext returns null within unit test - how do I test OWIN authentication within a unit test?
GetOwinContext calls context.GetOwinEnvironment(); which is
private static IDictionary<string, object> GetOwinEnvironment(this HttpContextBase context)
{
return (IDictionary<string, object>) context.Items[HttpContextItemKeys.OwinEnvironmentKey];
}
and HttpContextItemKeys.OwinEnvironmentKey is a constant "owin.Environment" So if you are add that in your httpcontext's Items, it will work.
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;
To make sure an OWIN context is available during your test (i.e., to fix the null reference exception when calling Request.GetOwinContext()
) you'll need to install the Microsoft.AspNet.WebApi.Owin
NuGet package within your test project. Once that is installed you can use the SetOwinContext
extension method on the request.
Example:
var controller = new MyController();
controller.Request = new HttpRequestMessage(HttpMethod.Post,
new Uri("api/data/validate", UriKind.Relative)
);
controller.Request.SetOwinContext(new OwinContext());
See https://msdn.microsoft.com/en-us/library/system.net.http.owinhttprequestmessageextensions.setowincontext%28v=vs.118%29.aspx
That being said, I agree with the other answers for your specific use case -- provide an AppplicationUserManager instance or factory in the constructor. The SetOwinContext
steps above are necessary if you need to directly interact with the context your test will use.
You can just pass in the UserManager in the constructor of the AccountController, so it doesn't try to find it in the owinContext. The default constructor is not unit test friendly.