0

I am trying to mock httpContext using Moq framework to esnure that httContext.Current is not null when request comes from Unit test but couldn't really make it working.

After doing google, i came with following steps so for and not sure what steps are next before i make post call to Api controller.

step 1

Add Moq package to project

step 2

using Moq;

step 3

var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();
var response = new Mock<HttpResponseBase>();

request.Setup(r => r.UrlReferrer).Returns(new Uri("http://tempuri.org/?ReturnUrl=%2f"));
response.Setup(r => r.Cookies).Returns(new HttpCookieCollection());
context.Setup(c => c.Request).Returns(request.Object);
context.Setup(c => c.Response).Returns(response.Object);

Can someone help me out for the next steps i need to do before making Post controller request.

simbada
  • 940
  • 4
  • 24
  • 43
  • You should refactor your code to decouple it from `HttpContext` to make it more testable. Having to mock things you have no control over usually creates more problems than it solves. The level of difficulty encountered trying to create a unit test is a direct indication of how well or how bad your code is constructed. – Nkosi Jul 05 '16 at 10:51
  • Possible duplicate of [Testing a Web API method that uses HttpContext.Current.Request.Files?](http://stackoverflow.com/questions/31189028/testing-a-web-api-method-that-uses-httpcontext-current-request-files) – Maxim Kosov Jul 05 '16 at 11:38

2 Answers2

0

First of all, don't use HttpContext.Current, because it does not support unit testing. Inside your Controller there are Request and Response properties which can be used to access any info about Request or Response. Use them instead of HttpContex.Current.

Inside you unit tests you can set your own ControllerContext. Please, look at another stackoverflow question which describes how to fake ControllerContext in Web Api:

Testing a Web API method that uses HttpContext.Current.Request.Files?

Community
  • 1
  • 1
Maxim Kosov
  • 1,930
  • 10
  • 19
  • How HttpContext.Current does not support unit testing? 2) how how i use HttpContext, Request, and Reponse instead of HttpContex.Current? – simbada Jul 05 '16 at 09:03
  • Also, i probably can't do new ControllerContext becuase i have web api controller not MVC .. – simbada Jul 05 '16 at 09:04
  • OK, thats right. In WebApi you can't have access to HttpContext, but everything you need to know about Request or Response can be received from `Request` and `Response` properties of controller. And you still can set your own `ControllerContext` to controller, but in WebApi it can't have `HttpContextBase` in constructor. – Maxim Kosov Jul 05 '16 at 11:43
0

In your case it might be a lot easier to write integration tests.

    [Test]
    public async Task get_should_succeed()
    {
        //arrange
        var url = string.Format("{0}{1}", BaseUrl, "controller");

        using(var httpServer = CreateHttpServer())
        using (var client = CreateHttpInvoker(httpServer))
        {
            using (var request = CreateHttpRequest(HttpMethod.Get, url))
            //act
            using (var response = await client.SendAsync(request, CancellationToken.None))
            {
                //assert
                Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
            }
        }
    }

A simplified version of ControllerTestBase:

public abstract class ControllerTestBase
{
    protected ControllerTestBase()
    {
        BaseUrl = "http://localhost/api/";
    }

    public string BaseUrl { get; set; }

    public static HttpServer CreateHttpServer()
    {
        var httpConfiguration = WebApiConfig.Register();
        return new HttpServer(httpConfiguration);
    }

    public static HttpMessageInvoker CreateHttpInvoker(HttpServer httpServer)
    {
        return new HttpMessageInvoker(httpServer);
    }

    public HttpRequestMessage CreateHttpRequest(HttpMethod httpMethod, string url)
    {
        return new HttpRequestMessage(httpMethod, url);
    }
}
Stephen Zeng
  • 2,748
  • 21
  • 18
  • 1
    i did not understand a single line what you are trying to say – simbada Jul 05 '16 at 09:22
  • Sorry if it is clear enough. Basically by using this code you can spin up a small web service in memory thereby you can define your input then assert the output. Shameless recommend you check this one: http://stephenzeng.com/Home/View/17 – Stephen Zeng Jul 05 '16 at 09:26
  • So you mean to say that writing integration test (as explained in the link you shared) will avoid the need the need of faking httpContext? correct? – simbada Jul 05 '16 at 09:30
  • That's right. This way you won't need to mock it, while the testing environment is still isolated and can be auto executed in your CI process. – Stephen Zeng Jul 05 '16 at 13:32