Reputation: 8201
As the architecture of ASP.NET Core 1.0 (ex MVC 6 / ASP.NET 5.0) changed significantly, how would one go about unit testing the routing?
As an example, I like the libraries such as this one (as for <= MVC 5): https://github.com/AnthonySteele/MvcRouteTester
Something down the lines of fluent extension methods:
routes.ShouldMap("/").To<HomeController>(x => x.Index());
Upvotes: 28
Views: 6840
Reputation: 885
Actually it is not quite hard to write your own route testing framework. I implemented route testing in MyTested.AspNetCore.Mvc and it works quickly and without any problem - https://github.com/ivaylokenov/MyTested.AspNetCore.Mvc
You can take a look at the code but basically, you need the following:
With these steps in mind, even tests like the following work correctly:
// action
public class NormalController : Controller
{
[HttpPost]
public IActionResult UltimateModelBinding(
ModelBindingModel model,
[FromServices]IUrlHelperFactory urlHelper)
{
return null;
}
}
// model
public class ModelBindingModel
{
[FromBody]
public RequestModel Body { get; set; }
[FromForm(Name = "MyField")]
public string Form { get; set; }
[FromQuery(Name = "MyQuery")]
public string Query { get; set; }
[FromRoute(Name = "id")]
public int Route { get; set; }
[FromHeader(Name = "MyHeader")]
public string Header { get; set; }
}
// unit test
MyMvc
.Routes()
.ShouldMap(request => request
.WithLocation("/Normal/UltimateModelBinding/100?myQuery=Test")
.WithMethod(HttpMethod.Post)
.WithJsonBody(new
{
Integer = 1,
String = "MyBodyValue"
})
.WithFormField("MyField", "MyFieldValue")
.WithHeader("MyHeader", "MyHeaderValue"))
.To<NormalController>(c => c.UltimateModelBinding(
new ModelBindingModel
{
Body = new RequestModel { Integer = 1, String = "MyBodyValue" },
Form = "MyFieldValue",
Route = 100,
Query = "Test",
Header = "MyHeaderValue"
},
From.Services<IUrlHelperFactory>()));
P. S. Do not write such actions.
Upvotes: 4
Reputation: 13699
Alright... I did ping the ASP.NET team and asked them how they proceeded to do their tests.
You can't unit test without mocking the world. You have to do integration/functional tests.
Routing can come from many places (attributes, pre-defined routes, areas, etc) and can even be altered by middleware. Including all those scenarios in a test would need to setup some massive dependency tree while there is an easier way to test it.
Basically, they are creating a TestStartup.cs
, self-hosting the app in the test process and hitting itself to see how it behaves. They override the results and... that's pretty much it.
I think I've given you all the possible tools here to actually bootstrap something for yourself.
Upvotes: 15