10

I'm writing some unit tests for a method that takes an HttpContext as a parameter. I want to test that the behavior is as expected when the request is a POST.

When creating a System.Net.HttpWebRequest it's easy to set the method, but I can't see a way to specify the method when creating a System.Web.HttpRequest which is what's used in HttpContext.

Any ideas?

For context the method is called by an httphandler and it is supposed to throw a 405 if the request is not a POST. I know that I can filter the allowable methods with the Verbs property in the web.config, and I will, however there's nothing stopping somebody in the future from changing the verbs property to allow other methods in which case I want the handler to take care of it itself.

Helper method currently in use:

    private HttpContext GetHttpContext(string requestUrl)
    {
        var httpRequest = new HttpRequest("", requestUrl, "");            
        var stringWriter = new StringWriter();
        var httpResponce = new HttpResponse(stringWriter);
        return new HttpContext(httpRequest, httpResponce);
    }
John Saunders
  • 160,644
  • 26
  • 247
  • 397
mdchris
  • 103
  • 1
  • 4
  • Use HttpContext.Current.Request.HttpMethod. Via http://stackoverflow.com/questions/6898598/http-verb-of-current-http-context – Bless Yahu Dec 03 '12 at 22:55
  • 1
    HttpMethod is a getter only, not a setter, so won't work for testing. – mdchris Dec 03 '12 at 22:59
  • 1
    I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders Dec 04 '12 at 02:07
  • I just read somewhere that `HttpContext.Current` is writeable. – John Saunders Dec 04 '12 at 02:18

1 Answers1

8

I would recommend researching mocking objects for the purpose of unit testing. There are a few mocking frameworks available for .NET that facilitate exactly this type of test.

For example, the article here sets the HttpMethod using the Moq framework.

From the article:

public ContextMocks(Controller onController, string HTTPMethod)
{
    //...
    Request = new Moq.Mock<HttpRequestBase>();
    Request.Setup(x => x.HttpMethod).Returns(HTTPMethod);
    //...
}

That said, if this is a one-off test, and I can't stress that enough, and the overhead incurred by introducing object mocking is unnecessary in your particular situation, the following reflection will set the HttpMethod:

typeof(HttpRequest).GetField("_httpMethod", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(httpRequest, "POST");

As I mentioned previously, if testing with HttpContext, HttpRequest, etc. are or will become a recurring theme, then take advantage of a mocking framework. You will save yourself time in the long run.

cokeman19
  • 2,405
  • 1
  • 25
  • 40
  • Thanks, I was thinking about it last night and figured if there was no easier method I would have to just use reflection, but wanted to avoid that option if I could as there's no guarantee of a private field existing after a version change. I figured mocking would be what i'd have to do, was just hoping it wasn't required and I as just missing something. – mdchris Dec 04 '12 at 14:22
  • Well looks like i'm stuck using reflection, HttpRequest is sealed so I can't mock it. This is not an MVC app so the context uses HttpRequest instead of HttpRequestBase... – mdchris Dec 04 '12 at 14:53