Mocking The RouteData Class in System.Web.Routing for MVC applications
Asked Answered
A

2

35

I'm trying to test some application logic that is dependent on the Values property in ControllerContext.RouteData.

So far I have

// Arrange
var httpContextMock = new Mock<HttpContextBase>(MockBehavior.Loose);
var controllerMock = new Mock<ControllerBase>(MockBehavior.Loose);
var routeDataMock = new Mock<RouteData>();

var wantedRouteValues = new Dictionary<string, string>();
wantedRouteValues.Add("key1", "value1");
var routeValues = new RouteValueDictionary(wantedRouteValues);

routeDataMock.SetupGet(r => r.Values).Returns(routeValues);  <=== Fails here

var controllerContext = new ControllerContext(httpContextMock.Object, routeDataMock.Object, controllerMock.Object);

The unit test fails with: System.ArgumentException: Invalid setup on a non-overridable member: r => r.Values

Creating a fake RouteData doesn't work either as the constructor is RouteData(RouteBase,IRouteHandler).

The important class here is the abstract class RouteBase which has the method GetRouteData(HttpContextBase) which returns an instance of RouteData, the class I'm trying to fake. Taking me around in circles!

Any help on this would be most welcome.

Antibiotic answered 12/6, 2009 at 11:30 Comment(0)
N
67

RouteData also has a constructor that takes no arguments. Simply create one and add the values to it that you want. No need to mock it when you can create one.

 var routeData = new RouteData();
 routeData.Values.Add( "key1", "value1" );

 var controllerContext = new ControllerContext(httpContextMock.Object, routeData, controllerMock.Object);
Naught answered 12/6, 2009 at 12:1 Comment(1)
Lol, thank you. This was a case of over thinking the problem on my part. Very simple. Cheers.Antibiotic
S
1

I'm very new to TDD in conjunction with mock objects, but a lesson I learned early on from a colleague was not to mock types you don't own. Thus, don't try to mock RouteData. The idea was originally conceived by Joe Walnes (though I can't find where he said it).

Sacramentarian answered 12/6, 2009 at 12:23 Comment(3)
Actually one of the reasons Microsoft developed the HttpContextBase was so that you could mock it. That's a very complex object, but frequently used in web testing. There are some excellent examples of using Moq to test your routes in Steven Sanderson's Pro ASP.NET MVC 2.Jahdiel
So how am I supped to test my helpers that depend on things like RouteData.. If you say that I am not supposed to mock classes I dont own? Tests cannot be written then or possibly the way the class I am testing needs to be more abstracted? Can't be bother with changing my class now.. it works I just need unit tests to proove it :DSaba
If you don't mock those types that you don't own, the alternative is to instantiate them - which effectively means that your test is covering them. You definitely shouldn't be testing the types that you don't own, so what is the alternative?Layard

© 2022 - 2024 — McMap. All rights reserved.