Skip to content

Testing

The GenHTTP.Testing package provides an easy way to write component tests for your application using a test framework of your choice. It provides both the ability to host your project in an isolated mode as well as convenience methods to run HTTP requests against your server.

Writing Tests

The following code shows how the TestHost can be used to spin up a server instance hosting the functionality of the app to be tested and how to run requests against this instance.

using GenHTTP.Testing;

[TestClass]
public sealed class MyTests
{

    [TestMethod]
    public async Task TestMyApp()
    {
        var app = ... // setup your app here

        await using var runner = await TestHost.RunAsync(app);

        using var response = await runner.GetResponseAsync("/some/path");

        Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
    }

}

The framework uses the HttpClient to execute requests, so that the semantics are the same, e.g. when performing POST requests with a body:

var request = runner.GetRequest();

request.Method = HttpMethod.Post;
request.Content = new StringContent("My Body");

using var response = await runner.GetResponseAsync(request);

Choosing an Engine

By default the test host runs on the internal engine. To verify that an application behaves the same on another engine, pass a ServerEngine - the same enum the server reports through IServer.ServerEngine:

await using var runner = await TestHost.RunAsync(app, engine: ServerEngine.Kestrel);

The Ioxide engine depends on io_uring and is therefore Linux-only; it cannot be hosted on Windows or macOS.

Response Handling

The test framework provides some extension methods to simplify reading typed responses.

using var response = await runner.GetResponseAsync();

var typed = await response.GetContentAsync<MyType>();

var typedNullable = await response.GetOptionalContentAsync<MyType>(); // might be null

Those methods allows to deserialize all formats supported by the GenHTTP framework (JSON, XML, YAML, form encoded, Protobuf).

var header = response.GetHeader("X-My-Header");
var contentType = response.GetContentHeader("Content-Type");

Accessing the Live Server

If a test needs the actual URL the server is listening on (e.g. to hand it to another library), use GetUrl(). TestHost.NextPort() reserves the next free port used by the test infrastructure, in case you need to bind additional resources alongside the server under test.

var url = runner.GetUrl("/some/path");