2

I have a web API project that I want to test with unit tests.

In the test class I create a HttpClient that is supposed to redirect the HTTP calls directly to my controllers:

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/") };
}

In the service project I have this class that calls config.MapHttpAttributeRoutes(), which works in prod but not when called by the test:

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

My controllers use attribute routing:

[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)
    {...}
}

When I use the HttpClient to make a call I get

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

and inspecting the httpClient with the debugger I see httpClient.handler.Configuration.Routes.Count == 0, so mapping the routing attributes didn't work

Q: What is the correct way to set up the fake HttpClient so my unit tests can use it to call the controllers?

3
  • Have you taken a look here? learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/… Commented Apr 19, 2017 at 18:58
  • 1
    server defaults to localhost when used in testing. So your default address is not going to work. Also this would be categorized as an integration test. not a unit test. Commented Apr 19, 2017 at 19:03
  • Take a look at how I did something similar here in this answer. stackoverflow.com/a/40423984/5233410 Commented Apr 19, 2017 at 19:10

1 Answer 1

1

HttpConfiguration config is not being assigned to the server so the settings are not being applied. The method applied the mapping to the config but didn't assign the config to the server when it was initialized.

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;
}

In the test the client can then make a call like

using(var client = GetInMemoryServerClient()) {
    var url = "api/groups/abc/sets/xyz/items/item123";
    var response = await client.GetAsync(url);
    //...do something with response
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.