Reputation: 693
I am trying to unit test the routings in my ASP.NET Web API 2 controllers. I am strictly following the recipe 11-6 in the newly released book ASP.NET Web Api 2 Recipes. Here is my controller:
[RoutePrefix("api/account")]
public class AccountController : ApiController
{
private AccountService _accountService;
public AccountController(AccountService service)
{
_accountService = service;
}
[Route("{id}")]
public IHttpActionResult Get(string id)
{
return Ok(_accountService.Get(id));
}
[Route("all")]
public IHttpActionResult GetAll()
{
return Ok(_accountService.GetAll());
}
}
And here are my unit tests (xunit):
public class AccountRoutingTest
{
readonly HttpConfiguration _config;
public AccountRoutingTest()
{
_config = new HttpConfiguration();
_config.MapHttpAttributeRoutes();
_config.EnsureInitialized();
}
[Theory]
[InlineData("http://acme.com/api/account/john")]
public void GetRoutingIsOk(string url)
{
var request = new HttpRequestMessage(HttpMethod.Get, url);
var routeTester = new RouteContext(_config, request);
Assert.Equal(typeof(AccountController), routeTester.ControllerType);
Assert.True(routeTester.VerifyMatchedAction(Reflection.GetMethodInfo((AccountController c) => c.Get(""))));
}
[Theory]
[InlineData("http://acme.com/api/account/all")]
public void GetAllRoutingIsOk(string url)
{
var request = new HttpRequestMessage(HttpMethod.Get, url);
var routeTester = new RouteContext(_config, request);
Assert.Equal(typeof(AccountController), routeTester.ControllerType);
Assert.True(routeTester.VerifyMatchedAction(Reflection.GetMethodInfo((AccountController c) => c.GetAll())));
}
}
The first unit test passes but the second one fails. I have isolated the problem to be in the RouteContext helper class in the following line, where the GetActionMapping method only detects the Get(id) action - not the GetAll():
_actionMappings = actionSelector.GetActionMapping(descriptor)[request.Method.ToString()];
I have tried to explicitly decorate the GetAll() action method with the [HttpGet] attribute and to switch from attribute routing to centralized routing - but without success. I am running out of ideas. Why is the GetAll() action - and all other actions except the Get(id) action - not detected by the GetActionMapping method?
The routing is fine when tested from a browser or Fiddler.
Upvotes: 1
Views: 361
Reputation: 27187
Looks like a tiny bug :)
Change
_actionMappings = actionSelector.GetActionMapping(descriptor)[request.Method.ToString()];
to:
_actionMappings = actionSelector.GetActionMapping(descriptor).
SelectMany(x => x).Where(x => x.SupportedHttpMethods.Contains(request.Method));
Upvotes: 2