ASP.NET 单元测试不映射路由

ASP.NET Unit testing doesn't map routes

我有一个 Web API 项目,我想用单元测试来测试它。

在测试中 class 我创建了一个 HttpClient 应该将 HTTP 调用直接重定向到我的控制器:

public static HttpClient GetInMemoryServerClient(HttpConfiguration serverConfig)
{
    var config = serverConfig ?? new HttpConfiguration();
    MyService.WebApiConfig.Register(config, isTest: true);
    var server = new HttpServer();
    server.Configuration.Services.Replace(typeof(IHttpActionInvoker), server.Configuration.Services.GetActionInvoker());
    return new HttpClient(server) { BaseAddress = new Uri("http://fakehost:9999/") };
}

在服务项目中,我有一个调用 config.MapHttpAttributeRoutes() 的 class,它在产品中有效,但在测试调用时无效:

public class WebApiConfig{
    //...
    public static void Register(HttpConfiguration config) // this is called in Global.asax.cs
    {
        Register(config, false);
    }

    public static Register(HttpConfiguration config, bool isTest){
        //... various config and dependency injection setup here
        config.MapHttpAttributeRoutes();
    }
}

我的控制器使用属性路由:

[RoutePrefix("api/groups/{groupId}/sets/{setId:minlength(1)}/items")]
public class ItemsController : BaseController
{
    [Route("{itemId:minlength(1)}")]
    [HttpGet]
    public async Task<API.Item> Get(string groupId, string setId, string itemId)
    {...}
}

当我使用 HttpClient 拨打电话时,我收到

{"Message":"No HTTP resource was found that matches the request URI 'http://fakehost:9999/api/groups/abc/sets/xyz/items/item123'."}

并使用我看到的调试器检查 httpClient httpClient.handler.Configuration.Routes.Count == 0,因此映射路由属性不起作用

问:设置假 HttpClient 以便我的单元测试可以使用它来调用控制器的正确方法是什么?

HttpConfiguration config 未分配给服务器,因此未应用设置。该方法将映射应用于配置,但在初始化时未将配置分配给服务器。

public static HttpClient GetInMemoryServerClient(HttpConfiguration serverConfig = null) {
    var config = serverConfig ?? new HttpConfiguration();
    MyService.WebApiConfig.Register(config, isTest: true);
    var server = new HttpServer(config); //<-- pass config to server        
    var client = new HttpClient(server);
    //Server defaults to localhost so setting client to localhost as well
    client.BaseAddress = new Uri("http://localhost"); 
    return client;
}

在测试中客户端可以调用

using(var client = GetInMemoryServerClient()) {
    var url = "api/groups/abc/sets/xyz/items/item123";
    var response = await client.GetAsync(url);
    //...do something with response
}