相关文章推荐
八块腹肌的眼镜  ·  browser/payable.sol:14 ...·  1 年前    · 
温文尔雅的菠萝  ·  vue ...·  1 年前    · 

I recently spent more time than I'd liked to figure out how to mock session state within an ASP.NET MVC test project. So here's the solution to that one, so hopefully you won't spend as much time as I did.

Important disclaimer: I was all over the dial to search for information, but most of what I dug up was related to ASP.NET MVC 3. This below solution works for me with ASP.NET MVC 4 and Moq as mocking framework.

Consider the following controller and single action-method.

public class HomeController : Controller public HomeController() // default constructor, usually you'd inject some repository or what not here, // but for this example we'll keep it simple public ViewResult TestMe() System.Diagnostics.Debug.WriteLine(Session[ " selectedMonth" ]); System.Diagnostics.Debug.WriteLine(Session[ " selectedYear" ]); return View();

The action-method references the current httpcontext 's Session collection. So if we instantiate a HomeController and try to obtain a ViewResult when calling the action-method, our unit test will fail with a NullReferenceException .

So, since the action-method wants to know about the Session collection, which resides in the HttpContext for the request to the method, we need to provide a HttpContext object. The below unit test code creates a mock HttpContext object, hooks it up to a mock Session object and passes it the instantiation of the controller - and the test will then pass, as now the action-method has a HttpContext to reach into and yank out the Session information.

[ TestMethod ] public void TestActionMethod() // create the mock http context var fakeHttpContext = new Mock(); // create a mock session object and hook it up to the mock http context var sessionMock = new HttpSessionMock {{ " selectedYear" , 2013 }, { " selectedMonth" , 10 }}; var mockSessionState = new Mock(); fakeHttpContext.Setup(ctx => ctx.Session).Returns(sessionMock); // ... and here's how to attach a http context identity, just in case you'll come to need that, too var fakeIdentity = new GenericIdentity( " mno@ucsj.dk" ); var principal = new GenericPrincipal(fakeIdentity, null ); fakeHttpContext.Setup(t => t.User).Returns(principal); // we'll need to hook our http context up to a controller context mock - because // we can't provide our controller with the http context mock directly var homeControllerMock = new Mock(); homeControllerMock.Setup(foo => foo.HttpContext).Returns(fakeHttpContext. Object ); // all set up, now we'll instantiate the controller and // pass our controller context object into its 'controllerContext' property var target = new HomeController() ControllerContext = homeControllerMock. Object // ... and the below call to the action method won't throw a nullReferenceException, // because now it has a Session state to dig into ViewResult result = target.TestMe(); // ... and so the test will pass Assert.AreEqual( string .empty, result.ViewName);

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Hey harleydk,
I'm newbie to unit testing. I tried your code but didn't work for our website.
I may have implemented it wrongly or it isn't fit for our situation.
I wrote a simple unit test for login functionality which uses WebSecurity object to validate user, session & cookies to store data and return boolean value. Here we got return value false because of WebSecurity so we removed it and used direct DB call to validate user. Now, when storing userdata into session and cookies we got exception of null.
So, please help us for this situation and let me know for any addition information you want.
Thank you.
Sign in · View Thread Answer Re: Your code didn't work for us, plz help for our situation Pin
Member 12594165 21-Sep-16 9:06
Member 12594165 21-Sep-16 9:06 I've installed the Moq nuget package and is trying to re-use your code.
I'm getting a lot of errors, though.
"var fakeHttpContext = new Mock(); -> "Cannot create instance of the abstract class or interface 'Moq.Mock'"
And where/what is HttpSessionMock?
A little sample code - or at least some info about versions and/or other dependencies - would really help a lot.
EDIT:
This code works with Moq 4.2.1312.1622:
// arrange var httpContextMock = new Mock<HttpContextBase>(); var sessionMock = new Mock<HttpSessionStateBase>(); sessionMock.Setup(n => n[ " SomeObject" ]).Returns( new DALTypes.Company() { CompanyID = 1 }); httpContextMock.Setup(n => n.Session).Returns(sessionMock. Object ); var sut = new SomethingController(); sut.ControllerContext = new ControllerContext(httpContextMock. Object , new RouteData(), sut); // act sut.DoStuff();

modified 17-Feb-14 12:00pm.

Sign in · View Thread