2

I'm attempting to run a couple basic unit tests on an ASP MVC controller, however at one point the controller needs to examine the IPrincipal User object like so:

ViewBag.Level = Security.GetLevel(User); 

Once the unit test enters the Create controller method, however, the above line throws a NullReferenceException as the User object is null.

Any ideas on how to set an IPrincipal for a unit test session?

Here's the test as I have it written right now. I attempted to access the User object and simply set it before the test goes into the Create method, however the intellisense isn't picking it up.

 [Test] public void a06_CloneFromDatabase() { using (AgentResources db = new AgentResources()) { var master = (from a in db.AgentTransmission where a.RecordStatus.Equals("C") select a).FirstOrDefault(); var result = _controlAgtTran.Create(master.ID, null, string.Empty, string.Empty, string.Empty, string.Empty, false) as ViewResult; var model = result.Model as AgentTransmission; Assert.AreEqual(model.ReferenceType, master.ReferenceType); } } 

EDIT

Following the post mentioned in the comments below I found a method to create a HttpContext session and apply and IPrincipal to that session. This works fine until the unit test moves into the controller where the HttpContext and IPrincipal User objects are all, once again, null.

Since it seems the instance of the controller I'm using has it's HttpContext property as read only (and the IPrincipal User property as well) does anyone know of a way to pass the HttpContext being used in the unit test inside the controller being tested? Also, if this is not possible, what is a usable method for testing RouteValues using ReSharper's unit tests?

 [SetUp] public void SetUp() { _controlAgtTran = new AgentTransmissionController(); /****Set up Current HTTP Context to pass Security.cs checks*****/ //Set up the HTTP Request var httpRequest = new HttpRequest("", "http://localhost:2574/", ""); //Set up the HTTP Response var httpResponse = new HttpResponse(new StringWriter()); //Set up the HTTP Context var httpContext = new HttpContext(httpRequest, httpResponse); var sessionContainer = new HttpSessionStateContainer("NEAROD", new SessionStateItemCollection(), new HttpStaticObjectsCollection(), 100, true, HttpCookieMode.AutoDetect, SessionStateMode.InProc, false); httpContext.Items["AspSession"] = typeof (HttpSessionState) .GetConstructor( BindingFlags.NonPublic | BindingFlags.Instance, null, CallingConventions.Standard, new[] {typeof (HttpSessionStateContainer)}, null) .Invoke(new object[] {sessionContainer}); //Assign the context HttpContext.Current = httpContext; } [Test] public void a01_IncompleteRecordGoesToEdit() { AgentTransmission agtTran = new AgentTransmission(); agtTran.ReferenceNumber = 95820518787; agtTran.ReferenceType = "S"; agtTran.EffectiveDate = DateTime.Now; agtTran.RelationshipEffDate = DateTime.Now; agtTran.RecordStatus = "N"; agtTran.CreatedDate = DateTime.Now; agtTran.CreatedOperator = "xTest1"; agtTran.FirstName = "Unit"; agtTran.LastName = "Test"; agtTran.ExtRepType = "EXTREPID"; agtTran.JIT = true; agtTran.SendToDRM = true; agtTran.SendToNMF = true; agtTran.WelcomeLetter = true; agtTran.OverrideRegionInd = false; //set IPrincipal string[] roles = {"LCO"}; IPrincipal principal = new GenericPrincipal(new GenericIdentity("SYMETRA\\NEAROD"), roles); HttpContext.Current.User = principal; IPrincipal user = HttpContext.Current.User; Assert.AreEqual(user, principal); //This passes Assert.AreEqual(principal, _controlAgtTran.User); //this fails var result = (RedirectToRouteResult)_controlAgtTran.Create(agtTran); //this crashes //Tests aren't run Assert.IsNotNull(result); Assert.AreEqual(3, result.RouteValues.Count); Assert.AreEqual("AgentTransmission", result.RouteValues["controller"]); Assert.AreEqual("Edit", result.RouteValues["action"]); } 
1

1 Answer 1

1

Following a similar solution mentioned in this post I added the following to the end of the SetUp() method.

 var controllerCtx = new ControllerContext(); controllerCtx.HttpContext = new HttpContextWrapper(HttpContext.Current); _controlAgtTran.ControllerContext = controllerCtx; 

Wrapping the current HttpContext inside an HttpContextBase property (the inappropriately named controllerCtx.HttpContext) the test now has access to the User and HttpContext properties of the controller. These properties were previously read-only when using just the HttpContext.Current session and therefore always null.

FYI - this is my first time unit testing with these objects so that explanation may be less than 100% correct. Please feel free to comment below and I'll make any necessary changes.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.