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()
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()
var
fakeHttpContext =
new
Mock();
var
sessionMock =
new
HttpSessionMock {{
"
selectedYear"
,
2013
}, {
"
selectedMonth"
,
10
}};
var
mockSessionState =
new
Mock();
fakeHttpContext.Setup(ctx => ctx.Session).Returns(sessionMock);
var
fakeIdentity =
new
GenericIdentity(
"
mno@ucsj.dk"
);
var
principal =
new
GenericPrincipal(fakeIdentity,
null
);
fakeHttpContext.Setup(t => t.User).Returns(principal);
var
homeControllerMock =
new
Mock();
homeControllerMock.Setup(foo => foo.HttpContext).Returns(fakeHttpContext.
Object
);
var
target =
new
HomeController()
ControllerContext = homeControllerMock.
Object
ViewResult result = target.TestMe();
Assert.AreEqual(
string
.empty, result.ViewName);
License
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
Re: Your code didn't work for us, plz help for our situation
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:
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);
sut.DoStuff();
modified 17-Feb-14 12:00pm.
Sign in
·
View Thread