I am trying to implement Microsoft.Owin.Testing/3.0.1 for WebApi 2 integration tests. Everything works fine except when I add attribute routing. The routes are not recognized or I am unable to register them properly. I'm pretty sure it has something to do with api controller dependency injection that is not used when testing.
My values api controller
[RoutePrefix("api")]
public class ValuesApiController : ApiController
{
private readonly ValuesControllerService _valuesControllerService;
public ValuesApiController(ValuesControllerService valuesControllerService)
{
_valuesControllerService = valuesControllerService;
}
// GET api/values
[HttpGet]
[Route("values")]
public async Task<IHttpActionResult> Get()
{
if (_valuesControllerService == null)
throw new ArgumentException("valuesControllerService");
return Ok(new[] { "value1", "value2" });
}
}
I am using Castle Windsor to resolve API Controllers using (source):
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new WindsorCompositionRoot(_container));
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(_container));
I'm registering my WebApi routes in Global.asax so it is registered properly when running the application (and not the tests).
public class WebApiApplication : HttpApplication
{
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
}
}
When testing, I call the registration after Startup. Here is a sample test which I use (test source):
[Test]
public async void GetValueTestForStartup1()
{
using (var server = TestServer.Create<Startup1>())
{
using (var client = new HttpClient(server.Handler))
{
var request = await client.GetAsync(_url);
Assert.IsTrue(request.IsSuccessStatusCode);
}
}
}
And here are some Startup implementations I tried:
internal class Startup1
{
public void Configuration(IAppBuilder app)
{
new Startup().ConfigureForIntegrationTests(app, x => x.Kernel.ComponentModelBuilder.AddContributor(new SingletonEqualizer()));
GlobalConfiguration.Configuration.Services.Replace(typeof(IAssembliesResolver), new TestWebApiResolver());
GlobalConfiguration.Configure(WebApiConfig.Register);
}
}
404 when executing a request
internal class Startup2
{
public void Configuration(IAppBuilder app)
{
new Startup().ConfigureForIntegrationTests(app, x => x.Kernel.ComponentModelBuilder.AddContributor(new SingletonEqualizer()));
GlobalConfiguration.Configure(WebApiConfig.Register);
GlobalConfiguration.Configuration.EnsureInitialized();
}
}
System.InvalidOperationException : This method cannot be called during the application's pre-start initialization phase.
internal class Startup3
{
public void Configuration(IAppBuilder app)
{
new Startup().ConfigureForIntegrationTests(app, y => y.Kernel.ComponentModelBuilder.AddContributor(new SingletonEqualizer()));
// Web API routes
GlobalConfiguration.Configuration.MapHttpAttributeRoutes();
GlobalConfiguration.Configuration.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
app.UseWebApi(GlobalConfiguration.Configuration);
GlobalConfiguration.Configuration.Services.Replace(typeof(IAssembliesResolver), new TestWebApiResolver());
}
}
500 Internal Server error (probably because there is no parameterless constructor found).
Complete sourceproject is located here: https://github.com/jvanderbiest/OwinTestingWebApi
There is a similar SO question here about AutoFac. I must have looked over that response but the key to all of this is to register everything with your own HttpConfiguration
instead of using the GlobalConfiguration
object.
I have updated the github code so the test is working fine now!