Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Add test cookie to Request in C# unit test

How I can add test cookie to request so I can test my code from Unit test. Consider a code like this:

public ActionResult Dashboard()
{
    if (Request.Cookies["usercookie"] == null)
    {
        return RedirectToAction("Index");
    }
    return View();
}

I mock everything, but I don't know how I can add something to cookie so this line Request.Cookies["usercookie"] not return null. As now it is null and returning me this error:

{"Object reference not set to an instance of an object."}

This is one of my unit test methods:

[TestMethod]
[TestCategory("Unit")]
public void Login_ShouldValidateUserAndLoginSuccessfully()
{
    using (var kernel = new NSubstituteMockingKernel())
    {
        // Setup the dependency incjection
        kernel.Load(new EntityFrameworkTestingNSubstituteModule());

        // Create test request data 
        var request = new LogInRequest { UserName = "test", Password = "test" };

        var fakeResponseHandler = new FakeResponseHandler();
        fakeResponseHandler.AddFakeResponse(new Uri("http://localhost/test"), new HttpResponseMessage(HttpStatusCode.OK));
        ConfigurationManager.AppSettings["SearchApiBaseUrl"] = "http://test/internal";
        var server = new HttpServer(new HttpConfiguration(), fakeResponseHandler);
        var httpClient = new HttpClient(server);

        var fakeCookieManager = new FakeCookieManager();
        var authenticationService = Substitute.For<IAuthenticationService>();
        var newUser = Fake.GetNewUser(1);
        var newUserClaim = Fake.GetNewUserClaim(1, newUser.Id, "http://test/identity/claims/loans");
        authenticationService.GetUserByEmailPasswordAsync(request.UserName, request.Password).Returns(newUser);
        authenticationService.GetUserClaimByEmailAndPasswordAsync(request.UserName, request.Password).Returns(newUserClaim);
        var controller = new HomeController(httpClient, fakeCookieManager, null, authenticationService);
        Fake.SetFakeAuthenticatedControllerContext(controller);
        controller.HttpContext.Session["ReturnUrl"] = "/search"; 
        var result = controller.Login(request);
        Assert.IsNotNull(result);
    }
}

This is a class in Fake for Httpcontext:

    public static HttpContextBase InitialiseFakeHttpContext(string url = "")
    {
        var HttpContextSub = Substitute.For<HttpContextBase>();
        var RequestSub = Substitute.For<HttpRequestBase>();
        var ResponseSub = Substitute.For<HttpResponseBase>();
        var serverUtilitySub = Substitute.For<HttpServerUtilityBase>();
        var itemsSub = Substitute.For<IDictionary>();
        HttpContextSub.Request.Returns(RequestSub);
        HttpContextSub.Response.Returns(ResponseSub);
        HttpContextSub.Server.Returns(serverUtilitySub);
        var cookie = Substitute.For<HttpResponseBase>();
        HttpContextSub.Response.Returns(cookie);
        return HttpContextSub;
    }
like image 463
Alma Avatar asked Jan 14 '17 00:01

Alma


2 Answers

Here is an example unit test where a cookie is set on the request.

Used NSubstitute framework to mock the http context and then setup the request cookies property. Applied the mocked http context to the controller context to simulate a request.

[TestClass]
public class MyControllerTests {
    [TestMethod]
    public void Request_Cookies_Should_Not_Be_Null() {
        //Arrange
        var cookies = new HttpCookieCollection();
        cookies.Add(new HttpCookie("usercookie"));

        var mockHttpContext = Substitute.For<HttpContextBase>();
        mockHttpContext.Request.Cookies.Returns(cookies);

        var sut = new MyController();
        sut.ControllerContext = new ControllerContext {
            Controller = sut,
            HttpContext = mockHttpContext
        };

        //Act
        var result = sut.Dashboard() as ViewResult;

        //Assert
        Assert.IsNotNull(result);
    }

    public class MyController : Controller {
        public ActionResult Dashboard() {
            if (Request.Cookies["usercookie"] == null) {
                return RedirectToAction("Index");
            }
            return View();
        }
    }
}

Update:

Here is an updated version of the test using a manually created mocked HttpContext.

[TestClass]
public class MyControllerTests {
    [TestMethod]
    public void Request_Cookies_Should_Not_Be_Null() {
        //Arrange
        var cookies = new HttpCookieCollection();
        cookies.Add(new HttpCookie("usercookie"));

        var mockHttpContext = new MockHttpContext(cookies);

        var sut = new MyController();
        sut.ControllerContext = new ControllerContext {
            Controller = sut,
            HttpContext = mockHttpContext
        };

        //Act
        var result = sut.Dashboard() as ViewResult;

        //Assert
        Assert.IsNotNull(result);
    }

    public class MyController : Controller {
        public ActionResult Dashboard() {
            if (Request.Cookies["usercookie"] == null) {
                return RedirectToAction("Index");
            }
            return View();
        }
    }


    private class MockHttpContext : HttpContextBase {
        private readonly MockRequest request;
        public MockHttpContext(HttpCookieCollection cookies) {
            this.request = new MockRequest(cookies);
        }

        public override HttpRequestBase Request {
            get {
                return request;
            }
        }

        public class MockRequest : HttpRequestBase {
            private readonly HttpCookieCollection cookies;
            public MockRequest(HttpCookieCollection cookies) {
                this.cookies = cookies;
            }

            public override HttpCookieCollection Cookies {
                get {
                    return cookies;
                }
            }
        }

    }
}
like image 182
Nkosi Avatar answered Sep 24 '22 09:09

Nkosi


This is the same thing using MOQ framework

MockContext class used to mock the HTTP context

public class MockContext
{
    public Mock<RequestContext> RoutingRequestContext { get; private set; }
    public Mock<HttpContextBase> Http { get; private set; }
    public Mock<HttpServerUtilityBase> Server { get; private set; }
    public Mock<HttpResponseBase> Response { get; private set; }
    public Mock<HttpRequestBase> Request { get; private set; }
    public Mock<HttpSessionStateBase> Session { get; private set; }
    public Mock<ActionExecutingContext> ActionExecuting { get; private set; }
    public HttpCookieCollection Cookies { get; private set; }

    public MockContext()
    {
        this.RoutingRequestContext  = new Mock<RequestContext>(MockBehavior.Loose);
        this.ActionExecuting        = new Mock<ActionExecutingContext>(MockBehavior.Loose);
        this.Http                   = new Mock<HttpContextBase>(MockBehavior.Loose);
        this.Server                 = new Mock<HttpServerUtilityBase>(MockBehavior.Loose);
        this.Response               = new Mock<HttpResponseBase>(MockBehavior.Loose);
        this.Request                = new Mock<HttpRequestBase>(MockBehavior.Loose);
        this.Session                = new Mock<HttpSessionStateBase>(MockBehavior.Loose);
        this.Cookies                = new HttpCookieCollection();

        this.RoutingRequestContext.SetupGet (c => c.HttpContext).Returns(this.Http.Object);
        this.ActionExecuting.SetupGet       (c => c.HttpContext).Returns(this.Http.Object);
        this.Http.SetupGet                  (c => c.Request).Returns(this.Request.Object);
        this.Http.SetupGet                  (c => c.Response).Returns(this.Response.Object);
        this.Http.SetupGet                  (c => c.Server).Returns(this.Server.Object);
        this.Http.SetupGet                  (c => c.Session).Returns(this.Session.Object);
        this.Request.Setup                  (c => c.Cookies).Returns(Cookies);
    }

}

and this is the test case

public void IndexTest()
    {
        // arrange
        MockContext mockContext = new MockContext();

        #region creating cookie
        HttpCookie cookie = new HttpCookie(Constant.COOKIE_ADMIN_USER_INFO,
                                         Config.DefaultCountryID.ToString());

        cookie.Values.Add(Constant.COOKIE_ADMIN_VALUE_COUNTRY_ID,
                          Config.DefaultCountryID.ToString());
        cookie.Values.Add(Constant.COOKIE_ADMIN_VALUE_LANGUAGE_ID,
                          Config.DefaultLanguageID.ToString());

        mockContext.Cookies.Add(cookie);
        #endregion
        #region Creating controller
        ControllerContext controllerContex = new ControllerContext()
        {
            HttpContext = mockContext.Http.Object
        };
        HomeController controller = new HomeController()
        {
            ControllerContext = controllerContex
        };
        #endregion

        // act
        var output = (ViewResult)controller.Index();
        var result = output.ViewData;

        // assert
        result.ShouldNotBeNull();
    }
like image 42
Shalinda Silva Avatar answered Sep 22 '22 09:09

Shalinda Silva