Skip to content

Stubbing an API

Martijn Bodeman edited this page Dec 19, 2023 · 15 revisions

There are plenty scenarios where it is not possible to just mock HttpClient. In such cases you can use MockHttpServer in combination with MockHttpHandler in order to create an API stub. Essentially, we want to host a server that listens to real incoming HTTP requests and fakes the responses that we configure using the MockHttpHandler.

Example scenarios where you may need MockHttpServer:

  • HttpClient cannot be injected.
  • parts of a specific client library/implementation are private/abstracted away.
  • the client implementation uses other API's like WebRequest, RestClient or others.
  • integration tests that need to 'touch' multiple parts of a client implementation which is consuming some API (for example a client with multiple delegating handlers, serialization, tracing).

Simply set up the requests as you would otherwise, but now provide the handler to the MockHttpServer and start the server. The server will bind to the specified host address and will respond to the configured requests. Next, provide the mock server its host URL as a base URL to your implementation, such that the mock server can handle the requests instead of the actual endpoint.

Example

// Create the handler.
using MockHttpHandler mockHttp = new MockHttpHandler();

// Configure setup(s).
mockHttp
    .When(matching => matching
        .Method("GET")
        .RequestUri("controller/*")
    )
    .Respond(with => with.JsonBody(new { id = 123, firstName = "John", lastName = "Doe" }))
    .Verifiable();

// Create server.
// Specify port 0 to bind to a free port, or otherwise provide an unused/free port.
using MockHttpServer server = new MockHttpServer(mockHttp, "http://127.0.0.1:0");
await server.StartAsync();

// Configure the subject under test to use the same host and port.
// For sake of example, we're using WebRequest here.

// Act
var request = WebRequest.Create($"{server.HostUrl}/controller/action");
request.Method = "GET";

// Assert
HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync();
response.StatusCode.Should().Be(HttpStatusCode.OK);
response.ContentType.Should().Be("application/json; charset=utf-8");
// Omitted assertion of response content for simplified example.

// Verify the request expectation as configured on the mock handler.
mockHttp.Verify();

// Clean up
await server.StopAsync();

The example illustrates it is not much dissimilar from just using MockHttpHandler alone.

Clone this wiki locally