Unit testing routing in ASP.NET Core 1.0 (ex MVC 6)

房东的猫 提交于 2019-12-09 05:02:24

问题


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());

回答1:


Alright... I did ping the ASP.NET team and asked them how they proceeded to do their tests.

Short answer

You can't unit test without mocking the world. You have to do integration/functional tests.

Slightly longer answer

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.

How they do it.

  • Startup.cs
  • RoutingTests.cs
  • TestResponseGenerator.cs

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.




回答2:


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:

  1. Mocked IApplicationBuilder to extract registered routes from
  2. Custom HTTP RouteFeature to pass RouteData around
  3. Custom ControllerActionInvoker to extract the binded models and stop MVC from processing the action
  4. Test builders and expression parsers to actually prepare and execute the test

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.



来源:https://stackoverflow.com/questions/32114999/unit-testing-routing-in-asp-net-core-1-0-ex-mvc-6

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!