117
[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.

6 Answers 6

71

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 );
Sign up to request clarification or add additional context in comments.

1 Comment

This one worked for me by allowing me to set a mock HttpContext on the controller.
43

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);

6 Comments

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 :(
If they're marshalled my reference, it's still possible via remoting, so it shouldn't be a problem.
@ChrisKimpton: As a last resort, there's always reflection ;-)
This works when attaching it to the controller, like this: controller.ControllerContext = new ControllerContext( new HttpContextWrapper(httpContextMock), new RouteData(), controller);
yes. you can indeed set .LogonUserIdentity -- _request.Setup(n => n.LogonUserIdentity).Returns((WindowsIdentity.GetCurrent));
|
16

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.

3 Comments

I can't seem to use the HttpRequest type - is that something else now?
This is not useful because all the fields in HttpRequest are immutable
I also had to use this to fix the RouteData stackoverflow.com/a/57005125/1594274
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.");
    }
}

2 Comments

Why'd you need to pass a fake application path?
The MVC code will execute it and throw a null exception if it's not there.
4

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

1 Comment

Links are broken - please include the code in your answer
-1
var httpResponse = new HttpResponseMessage(HttpStatusCode.OK);
httpResponse.Content = new StringContent("Your response text");

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.