Query string
You will also need to mock the query string in the HttpRequestBase object. To do this, you will need to build a graph of objects
ControllerContext HttpContextBase HttpRequestBase
As you are already mocking the ControllerContext your controller instance, you can use the following code to add the string of the manufactured query:
var queryString = new NameValueCollection { { "code", "codeValue" } }; var mockRequest = new Mock<HttpRequestBase>(); mockRequest.Setup(r => r.QueryString).Returns(queryString); var mockHttpContext = new Mock<HttpContextBase>(); mockHttpContext.Setup(c => c.Request).Returns(mockRequest.Object); mockControllerContext.Setup(c => c.HttpContext).Returns(mockHttpContext.Object);
Session
For a mocked session, use the same http context that was configured above to return the moker session object:
var mockSession = new Mock<HttpSessionStateBase>(); mockHttpContext.Setup(c => c.Session).Returns(mockSession.Object);
You can then set the values as you did using SetupGet , or you can also use Setup , as in
mockSession.Setup(s => s["token"]).Returns("fooToken")
If you want to verify that the value was set in the session, you can add something like this to the verification code:
mockSession.VerifySet(s => s["token"] = "tokenValue", Times.Once);
ActionResult Types
What I usually do is convert the result to the desired type using the as operator. It will return null if conversion is not possible. Therefore, the statement may look like this:
ViewResult result = controller.Index() as ViewResult; // Assert Assert.IsNotNull(result); Assert.AreEqual("fooView", result.ViewName);
Side note
If you have many similar tests in which the code uses a session and / or query string, for each test several layouts will be created that need to be created and configured.
You can add the installation method to your test class (which runs before each test) and move there all the code that builds the object graph using mocks. Thus, you have a new controller instance for each testing method, and for each part of the test you just need to configure the behavior and layout expectations.
For example, if you have this setup code in your test class:
private HomeController _homeController; private Mock<HttpSessionStateBase> _mockSession; private Mock<HttpRequestBase> _mockRequest; [SetUp] public void Setup() { _mockRequest = new Mock<HttpRequestBase>(); _mockSession = new Mock<HttpSessionStateBase>(); var mockHttpContext = new Mock<HttpContextBase>(); var mockControllerContext = new Mock<ControllerContext>(); mockHttpContext.Setup(c => c.Request).Returns(_mockRequest.Object); mockHttpContext.Setup(c => c.Session).Returns(_mockSession.Object); mockControllerContext.Setup(c => c.HttpContext).Returns(mockHttpContext.Object); _homeController = new HomeController(); _homeController.ControllerContext = mockControllerContext.Object; }
The code for each test will be summarized as follows:
[Test] public void Index_WhenNoTokenInSession_ReturnsDummyViewAndSetsToken() { // Arrange var queryString = new NameValueCollection { { "code", "dummyCodeValue" } }; _mockSession.Setup(s => s["token"]).Returns(null); _mockRequest.Setup(r => r.QueryString).Returns(queryString); // Act ViewResult result = _homeController.Index() as ViewResult; // Assert Assert.IsNotNull(result); Assert.AreEqual("dummy", result.ViewName); _mockSession.VerifySet(s => s["token"] = "tokenValue", Times.Once); } [Test] public void Index_WhenTokenInSession_ReturnsDefaultView() { // Arrange _mockSession.Setup(s => s["token"]).Returns("foo"); // Act ViewResult result = _homeController.Index() as ViewResult; // Assert Assert.IsNotNull(result); Assert.AreEqual(String.Empty, result.ViewName); }
In cases where these tests test this dummy index method
public ActionResult Index() { if (Session["token"] == null) { if (Request.QueryString["code"] != null) { Session["token"] = "tokenValue"; return View("dummy"); } } return View(); }