106
[TestMethod]
public void Home_Message_Display_Unknown_User_when_coockie_does_not_exist()
{
    var context = new Mock<HttpContextBase>();
    var request = new Mock<HttpRequestBase>();
    context
        .Setup(c => c.Request)
        .Returns(request.Object);
    HomeController controller = new HomeController();

    controller.HttpContext = context; //Here I am getting an error (read only).
    ...
 }

my base controller has an overrride of the Initialize that get's this requestContext. I am trying to pass this along but I am not doing something right.

protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
    base.Initialize(requestContext);
}

Where can I get more information on mocking my RequestContext and HttpContext using Moq? I am trying to mock cookies and the general context.

abatishchev
  • 92,232
  • 78
  • 284
  • 421
Geo
  • 8,329
  • 13
  • 61
  • 90

5 Answers5

62

HttpContext is read-only, but it is actually derived from the ControllerContext, which you can set.

 controller.ControllerContext = new ControllerContext( context.Object, new RouteData(), controller );
Sachin Kainth
  • 41,237
  • 78
  • 185
  • 289
tvanfosson
  • 490,224
  • 93
  • 683
  • 780
42

Create a request, response and put them both to HttpContext:

HttpRequest httpRequest = new HttpRequest("", "http://mySomething/", "");
StringWriter stringWriter = new StringWriter();
HttpResponse httpResponse = new HttpResponse(stringWriter);
HttpContext httpContextMock = new HttpContext(httpRequest, httpResponse);
Sklivvz
  • 28,698
  • 24
  • 111
  • 164
0100110010101
  • 5,971
  • 5
  • 31
  • 37
  • The question is about the *Base classes, ie HttpRequestBase, not HttpRequest - not sure why both are needed myself and even more annoying that they are "sealed". No way to set LogonUserIdentity :( – Chris Kimpton Oct 22 '10 at 08:57
  • If they're marshalled my reference, it's still possible via remoting, so it shouldn't be a problem. – 0100110010101 Oct 22 '10 at 11:46
  • 1
    @ChrisKimpton: As a last resort, there's always _reflection_ ;-) – Oliver Jan 15 '14 at 16:57
  • This works when attaching it to the controller, like this: controller.ControllerContext = new ControllerContext( new HttpContextWrapper(httpContextMock), new RouteData(), controller); – Andreas Vendel Jun 25 '14 at 13:31
  • yes. you can indeed set .LogonUserIdentity -- _request.Setup(n => n.LogonUserIdentity).Returns((WindowsIdentity.GetCurrent)); – KevinDeus Oct 16 '14 at 21:52
14

Thanks user 0100110010101.

It worked for me and here i had an issue while writing the testcase for the below code :

 var currentUrl = Request.Url.AbsoluteUri;

And here is the lines which solved the problem

HomeController controller = new HomeController();
//Mock Request.Url.AbsoluteUri 
HttpRequest httpRequest = new HttpRequest("", "http://mySomething", "");
StringWriter stringWriter = new StringWriter();
HttpResponse httpResponse = new HttpResponse(stringWriter);
HttpContext httpContextMock = new HttpContext(httpRequest, httpResponse);
controller.ControllerContext = new ControllerContext(new HttpContextWrapper(httpContextMock), new RouteData(), controller);

Might be helpful for the others.

Chandan Kumar
  • 4,017
  • 3
  • 36
  • 58
7

Here's how I used the ControllerContext to pass a fake Application path:

[TestClass]
public class ClassTest
{
    private Mock<ControllerContext> mockControllerContext;
    private HomeController sut;

    [TestInitialize]
    public void TestInitialize()
    {
        mockControllerContext = new Mock<ControllerContext>();
        sut = new HomeController();
    }
    [TestCleanup]
    public void TestCleanup()
    {
        sut.Dispose();
        mockControllerContext = null;
    }
    [TestMethod]
    public void Index_Should_Return_Default_View()
    {

        // Expectations
        mockControllerContext.SetupGet(x => x.HttpContext.Request.ApplicationPath)
            .Returns("/foo.com");
        sut.ControllerContext = mockControllerContext.Object;

        // Act
        var failure = sut.Index();

        // Assert
        Assert.IsInstanceOfType(failure, typeof(ViewResult), "Index() did not return expected ViewResult.");
    }
}
Ria
  • 9,576
  • 3
  • 29
  • 55
Xolartek
  • 71
  • 1
  • 2
5

Here is an example of how you can set this up: Mocking HttpContext HttpRequest and HttpResponse for UnitTests (using Moq)

Note the extension methods which really help to simplify the usage of this mocking classes:

var mockHttpContext = new API_Moq_HttpContext();

var httpContext = mockHttpContext.httpContext();

httpContext.request_Write("<html><body>".line()); 
httpContext.request_Write("   this is a web page".line());  
httpContext.request_Write("</body></html>"); 

return httpContext.request_Read();

Here is an example of how to write a Unit Test using moq to check that an HttpModule is working as expected: Unit Test for HttpModule using Moq to wrap HttpRequest

Update: this API has been refactored to

Dinis Cruz
  • 3,753
  • 2
  • 26
  • 46