James Law
James Law

Reputation: 6693

Unit Testing WebApi Controller Using In-Memory HttpServer - No HTTP resource was found

From this blog article by Yusef: http://blogs.msdn.com/b/youssefm/archive/2013/01/28/writing-tests-for-an-asp-net-webapi-service.aspx

I'm trying to set up some unit test for a WebApi project but continue to get:

"No HTTP resrouce was found that matches the request URI http://localhost/api/Filter"

Test case:

[TestMethod]
    public void TestMethod1()
    {
        HttpConfiguration config = new HttpConfiguration();
        config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}");
        HttpServer server = new HttpServer(config);
        using (HttpMessageInvoker client = new HttpMessageInvoker(server))
        {
            using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/api/Filter"))
            {
                request.Content = new StringContent(ValidJSONRequest);
                request.Content.Headers.Add("content", "application/json");
                using (HttpResponseMessage response = client.SendAsync(request, CancellationToken.None).Result)
                {
                    Assert.AreEqual(ValidJSONResponse, response.Content.ReadAsStringAsync().Result);
                }
            }
        };
    }

NB. ValidJSONRequest/ValidJSONResponse are string containing JSON objects.

Running in IIS express this routing works perfectly and behaves as expected and I can't for the life of me work out what's going on? What am I missing?

Upvotes: 1

Views: 3134

Answers (2)

James Law
James Law

Reputation: 6693

Right, I'm still not sure exactly what's going on here but I've found a workaround.

This blog article contains some details - effectively the controllers context needs to be loaded up into memory... http://www.tugberkugurlu.com/archive/challenge-of-solving-an-asp-net-web-api-self-hosting-problem-no-http-resource-was-found-that-matches-the-request-uri

So how to fix it? Add this test case to the test class and it works fine.

[TestMethod]
public void Filter_Test()
{
    FilterController controller = new FilterController();
}

Upvotes: 1

JotaBe
JotaBe

Reputation: 39015

The problem is that you're not specifying an id on your tested URL (http://localhost/api/Filter), and the configureed route doesn't have the id configured as optional.

So, either test a ULR that specifies an id, like http://localhost/api/Filter/1, or chagne the route configuration so that the id is optional, like this: instead of

config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}");

config.Routes.MapHttpRoute(
     name: "DefaultApi",
     routeTemplate: "api/{controller}/{id}",
     defaults: new { id = System.Web.Http.RouteParameter.Optional } // optional id
     );

In this way, the tested url will match the DefaultApi route.

Of course, you need a Postxxx method in your controller, because you're trying a POST action, and not specifying an action name neither in the tested URL, nor in the route definition. But, if you say it's working on local IIS, then this method must exist.

Upvotes: 0

Related Questions