The original question was a bit incorrect, because the problem happens only during controller testing How to return correct status code when enumeration of IEnumerable fails. ASP.NET WebApi
The question is how to properly test web api controller which returns IEnumerable when IEnumerable might throw an exception during deferred execution?
E.g. I have such API endpoint:
public class EntityController : ApiController
{
...
public IHttpActionResult Get()
{
return Ok(Session.Query<Entity>());
}
}
And corresponding test will always pass regardless of exception which might be thrown during query execution.
[Test]
public async Task Test()
{
var entityController = new EntityController(Session)
{
Configuration = new HttpConfiguration(),
Request = new HttpRequestMessage()
};
var response = await entityController.GetAll().ExecuteAsync(new CancellationTokenSource().Token);
response.EnsureSuccessStatusCode();
}
However this test will not pass if casting ToList inside the controller itself.
public class EntityController : ApiController
{
...
public IHttpActionResult Get()
{
return Ok(Session.Query<Entity>().ToList());
}
}
It seems to me that you would like to create integration tests to test your web api endpoints.
Your current test won't ever hit a media type formatter or other parts of the web api pipeline where issues can occur.
I recommend using the Microsoft.Owin.Testing nuget package in your test project. This will allow you to set up your web api controller in an in-memory web server for testing which will cover more of the web api pipeline.
Judging by your snippet of code, your web api controller does not have any dependencies on System.Web
so using OWIN for testing may suit your needs. Of course, this will not cover anything that is specific to your IIS setup or anything in the IIS pipeline outside of web api. However, it will catch exceptions thrown from the deferred execution of your Linq query
if you do not use ToList()
in your controller action.
To use Owin and Owin Testing you will need to follow these steps:
1. Add the Microsoft.Owin nuget package to the web project containing the web api controllers you wish to test.
2. Add an Owin Startup class to that web project:
public class Startup {
public virtual void Configuration(IAppBuilder builder) {
// if you want to move all your web api initialization
// and configuration to here then you can.
// Otherwise just leave this method empty
}
}
We will override the Configuration
method in the test project.
3. Add the Microsoft.AspNet.WebApi.Owin nuget package to your test project
4. Add the Microsoft.Owin.Testing nuget package to your test project.
5. Create a Test class in your test project:
public class TestClass {
private class TestStartup : Startup {
public override void Configuration(IAppBuilder app) {
// do your web api, IoC, etc setup here
var config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
// ...etc
app.UseWebApi(config);
}
}
[Test]
public void MyTest() {
// arrange
using (var server = TestServer.Create<TestStartup>()) {
// act
var response = server.CreateRequest("api/someroute/").GetAsync().Result;
// verify
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
}
}
}
Make sure the TestStartup
inner class derives from the Startup
class created in your web project in step two, this will ensure that web api will pick up your controllers from the web project. There are other methods, but this is simple and has the benefit of being able to reuse initialization code from the actual application if you were using Owin.
6. Profit
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With