Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly integration test Web Api controller with IEnumerable results?

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());
    }
}
like image 235
Vladimir Sachek Avatar asked Jul 16 '15 10:07

Vladimir Sachek


Video Answer


1 Answers

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

like image 173
Anish Patel Avatar answered Oct 01 '22 00:10

Anish Patel