Search code examples
c#asp.net-mvcunit-testingasp.net-corecookies

How to Mock HttpContext to set Response.Cookie.Append() in UnitTest


I need to mock HttpContext and append cookies to validate in controller.

Here is the unit Test I am trying but its failing with null exception.

HomeController.ControllerContext = new ControllerContext();
HomeController.ControllerContext.HttpContext = new DefaultHttpContext();
HomeController.ControllerContext.HttpContext.Response.Cookies.Append("mycookie", cookieValue, cookieOptions);

Here is the my controler where I am checking cooking null.

 public async Task<myDto> Identify() {

    // Get identifier from client
    var identifier = identifiersService.GetIdentifier(HttpContext);
    if (!await identifiersService.IsValidAsync(identifier)) {
        if (HttpContext != null && HttpContext.Request.Cookies["mycookie"] != null) {
            HttpContext.Response.Cookies.Delete("mycookie");
        }
        throw new MyException(Factory.INVALID);
    }

Any suggestion on how I can pass cookie from unittest to Controller to test. Thank you


Solution

  • You are setting the cookie on the response while you are checking it on the request.

    1. Mock the Cookies collection on the request
    2. Pass the mocked HttpContext to the ControllerContext
    var cookiesMock = new Mock<IRequestCookieCollection>();
    cookiesMock.SetupGet(c => c["mycookie"]).Returns(cookieValue);
    
    var httpContextMock = new Mock<HttpContext>();
    httpContextMock.Setup(ctx => ctx.Request.Cookies).Returns(cookiesMock.Object);
    
    HomeController.ControllerContext = new ControllerContext()
    {
        HttpContext = httpContextMock.Object
    };
    

    UPDATE #1

    If cookies is available then I need to delete the cookie. How I can I mock Response.Cookies.Delete()?

    Quite similarly what we did with the request cookies

    var responseCookiesMock = new Mock<IResponseCookies>();
    responseCookiesMock.Setup(c => c.Delete("mycookie"))
                       .Verifiable();
    httpContextMock.Setup(ctx => ctx.Response.Cookies)
                   .Returns(responseCookiesMock.Object);
    

    So, the full code would look like this

    const string CookieKey = "mycookie";
    var requestCookiesMock = new Mock<IRequestCookieCollection>();
    requestCookiesMock.SetupGet(c => c[CookieKey]).Returns(cookieValue);
    
    var responseCookiesMock = new Mock<IResponseCookies>();
    responseCookiesMock.Setup(c => c.Delete(CookieKey)).Verifiable();
    
    var httpContextMock = new Mock<HttpContext>();
    httpContextMock.Setup(ctx => ctx.Request.Cookies)
                    .Returns(requestCookiesMock.Object);
    httpContextMock.Setup(ctx => ctx.Response.Cookies)
                    .Returns(responseCookiesMock.Object);
    
    HomeController.ControllerContext = new ControllerContext()
    {
        HttpContext = httpContextMock.Object
    };