How do I mock the HttpContext in ASP.NET MVC using Moq?

C#asp.net MvcMockingMoqHttpcontext

C# Problem Overview


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

C# Solutions


Solution 1 - C#

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

Solution 2 - C#

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

Solution 3 - C#

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.

Solution 4 - C#

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.");
	}
}

Solution 5 - C#

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

Solution 6 - C#

var httpResponse = new HttpResponseMessage(HttpStatusCode.OK);
httpResponse.Content = new StringContent("Your response text");

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGeoView Question on Stackoverflow
Solution 1 - C#tvanfossonView Answer on Stackoverflow
Solution 2 - C#0100110010101View Answer on Stackoverflow
Solution 3 - C#Chandan KumarView Answer on Stackoverflow
Solution 4 - C#XolartekView Answer on Stackoverflow
Solution 5 - C#Dinis CruzView Answer on Stackoverflow
Solution 6 - C#Fabricio LeiteView Answer on Stackoverflow