Reputation: 923
I am unable to unit test one of my functions that contains HttpContext.Current.Request.LogonUserIdentity.Name
The error that I get is because LogonUserIdentity
is null.
I added this in my unit test in order to set a value for HttpContext.Current
because that was also null:
HttpContext.Current = new HttpContext(
new HttpRequest("", "http://localhost:8609", ""),
new HttpResponse(new StringWriter())
);
How can I assign a value to
LogonUserIdentity
so that I can test my function?
Upvotes: 3
Views: 2669
Reputation: 149
Not really the best mock, but sometimes you're trapped.
In this solution you must handle locally logged user (johndoe) on controller and/or in your db.
But works.
var mockRequest = new HttpRequest("", "http://tempuri.org", "");
HttpContext.Current = new HttpContext(
mockRequest,
new HttpResponse(new StringWriter())
);
mockRequest.GetType().InvokeMember(
"_logonUserIdentity",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.SetField | System.Reflection.BindingFlags.Instance,
System.Type.DefaultBinder,
mockRequest,
new object[] { WindowsIdentity.GetCurrent() }
);
Upvotes: 1
Reputation: 508
I spent a lot of time trying to mock HttpContext or HttpContextBase, then trying to shim with fakes WindowsIdentity class or HttpRequest.LogonUserIdentity property. Nothing works - you don't need completely mocked HttpContext because you want see real responses, not your mock set ups returned. Shims are just not generating for WindowsIdentity class ("due to internal limitations") and for LogonUserIdentity property (no reason given in fakes messages, it's just not there).
The best approach how to get testable HttpContext with request and response is described here: http://jonlanceley.blogspot.com/2015/08/unit-testing-part-2-faking-httpcontext.html
I was able to override LogonUserIdentity property in my fake request wrapper and set there whatever I need.
Upvotes: 1
Reputation: 1
You can mock it using (System.Web.Fakes) like this:
ShimHttpRequest.AllInstances.LogonUserIdentityGet = (a) => { return WindowsIdentity.GetCurrent(); };
Upvotes: 0
Reputation: 5318
You can mock the context as shown here
var requestMock = new Mock<HttpRequestBase>();
var contextMock = new Mock<HttpContextBase>();
var mockIIdentity = new Mock<IIdentity>();
mockIIdentity.SetupGet(x => x.Name).Returns("MyName");
WindowsIdentity windowsIdentity = mockIIdentity.Object as WindowsIdentity;
requestMock.Setup(x => x.LogonUserIdentity).Returns(windowsIdentity);
contextMock.Setup(x => x.Request).Returns(requestMock.Object);
yourControllerInstance.ControllerContext new ControllerContext(contextMock.Object, new RouteData(), yourControllerInstance)
I have also a test helper that I wrote, you can find it in Github and try using it, you can modify it to incorporate the above setup https://github.com/danielhunex/TestHelper
Upvotes: 0
Reputation: 247323
This is a sign of much bigger problem to come.
The LogonUserIdentity property exposes the properties and methods of the WindowsIdentity object for the currently connected user to Microsoft Internet Information Services (IIS). The instance of the WindowsIdentity class that is exposed by LogonUserIdentity tracks the IIS request token and provides easy access to this token for the current HTTP request being processed inside of ASP.NET. An instance of the WindowsIdentity class is automatically created so it does not need to be constructed to in order to gain access to its methods and properties.
Source (emphasis mine)
How can I assign a value to
LogonUserIdentity
so that I can test my function?
You can't. Not in a unit test as IIS is not available.
Avoid tightly coupling your code to untestable code you cannot control like HttpContext
and most of System.Web
namespace.
Instead, encapsulate them behind abstraction you control and can mock.
Upvotes: 2