1

In the process of writing an unit test for a Controller, I need to setup or initialize -

ControllerContext.HttpContext.Request.QueryString

What is the simplest way for setting this up so that I can actually pass the - ControllerContext.HttpContext.Request.QueryString - and have the controller tested?

1 Answer 1

7

You could use a mock framework in order to mock the HttpContext that the controller is working with.

For example with NSubstitute:

// arrange
var contextMock = Substitute.For<HttpContextBase>();
var requestMock = Substitute.For<HttpRequestBase>();
var queryString = new NameValueCollection();
queryString["foo"] = "bar";
requestMock.QueryString.Returns(queryString);
contextMock.Request.Returns(requestMock);
var sut = new SomeController();
sut.ControllerContext = new ControllerContext(contextMock, new RouteData(), sut);

// act
var actual = sut.SomeAction(); 

// assert
...

Of course you could have used any other mocking framework you like such as Moq or Rhino Mocks in order to mock the HttpContext.

By the way if you used view models (which you should always do in a properly designed ASP.NET MVC application) you wouldn't even cared about Request.QueryString because your controller action would now have taken a view model as argument:

public ActionResult SomeAction(MyViewModel model)
{
    ...
}

and the default model binder would have taken into account the binding of request parameters to model. You should avoid writing plumbing code in your controller action where you are extracting some data from query strings and stuffs.

Look how much more readable your unit test now becomes:

var model = new MyViewModel();
model.Foo = "bar";
var sut = new SomeController();

// act
var actual = sut.SomeAction(model); 

// assert
...

See? You don't need to care about plumbing code anymore.

Sign up to request clarification or add additional context in comments.

1 Comment

Just wondering if it is good practice to write the unit test in such a way on how the data will be incoming from the requester. So my controller is initiated by a GET with a QueryString so I am using a test string query and would want the model binder to create the object for me without mocking the concrete model on the controller. I know what you may say.. we should trust the model binder in live and just write unit tests for the functionality part regardless of entry point... but it feels like cheating by omitting the model binder? :(

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.