Reputation: 5090
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?
Upvotes: 1
Views: 4317
Reputation: 1038710
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.
Upvotes: 7