How to set query string value in Moq testing method

I have the following controller action method and I am writing unit test for this method

try { if ( Session["token"] == null) { //checking whether the user has already given the credentials and got redirected by survey monkey by checking the query string 'code' if (Request.QueryString["code"] != null) { string tempAuthCode = Request.QueryString["code"]; Session["token"] = _surveyMonkeyService.GetSurveyMonkeyToken(ApiKey, ClientSecret, tempAuthCode, RedirectUri, ClientId); } else { //User coming for the first time directed to authentication page string redirectUrlToSurveyMonkeyAuthentication = _surveyMonkeyService.GetUrlToSurveyMonkeyAuthentication(RedirectUri, ClientId, ApiKey); return Redirect(redirectUrlToSurveyMonkeyAuthentication); } } //User is in the same session no need for token again showing surveys without authentication var model = _surveyService.GetSurveys(User.Identity.Name); if (model.Count == 0) return View(CSTView.NoSurveyTracker.ToString()); return View(CSTView.Index.ToString(), model); } catch (Exception e) { return DisplayErrorView(e);//Even this returns a redirect method } 

And here is one of the unit test that I wrote for it,

  [Test] public void GetIndexPage_Returns_View_With_ValidToken() { var mockControllerContext = new Mock<ControllerContext>(); var mockSession = new Mock<HttpSessionStateBase>(); mockSession.SetupGet(s => s["SurveyMonkeyAccessToken"]).Returns(SampleToken); mockSession.SetupGet(c => c["code"]).Returns(SampleTempAuthCode); mockControllerContext.Setup(p => p.HttpContext.Session).Returns(mockSession.Object); _surveyTrackerController.ControllerContext = mockControllerContext.Object; _surveyServiceMock.Setup(x => x.GetSurveys(TestData.TestData.SampleUserName)).Returns(SurveyTrackerList); var result = _surveyTrackerController.GetIndexPage(); Assert.IsInstanceOf(typeof(ActionResult), result); Assert.AreEqual(((ViewResult)result).ViewName, "expected"); } 

When I try to run a test for its throw error: the object link is not set to the object instance, and the line number shows request.querystring, how to set the session variables in the testing methods, and can anyone suggest me what is the correct way to check the type the return action of the controller.

+6
source share
1 answer

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); //where mockHttpContext has been created in the code for the queryString above and setup to be returned by the controller context 

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(); } 
+15
source

All Articles