Is it possible to use Furl.Http with the OWIN Test

2019-06-01 07:51发布

问题:

I'm using the OWIN TestServer which provides me an HttpClient to do my in memory calls to the test server. I'm wondering if there's a way of passing in the existing HttpClient for Flurl to use.

回答1:

UPDATE: Much of the information below is no longer relevant in Flurl.Http 2.x. Specifically, most of Flurl's functionality is contained in the new FlurlClient object (which wraps HttpClient) and not in a custom message handler, so you're not losing functionality if you provide a different HttpClient. Further, as of Flurl.Http 2.3.1, you no longer need a custom factory to do this. It's as easy as:

var flurlClient = new FlurlClient(httpClient);

Flurl provides an IHttpClientFactory interface that allows you to customize HttpClient construction. However, much of Flurl's functionality is provided by a custom HttpMessageHandler, which is added to HttpClient on construction. You wouldn't want to hot-swap it out for an already instantiated HttpClient or you'll risk breaking Flurl.

Fortunately, OWIN TestServer is also driven by an HttpMessageHandler, and you can pipeline multiple when you create an HttpClient.

Start with a custom factory that allows you to pass in the TestServer instance:

using Flurl.Http.Configuration;
using Microsoft.Owin.Testing;

public class OwinTestHttpClientFactory : DefaultHttpClientFactory
{
    private readonly TestServer _testServer;

    public OwinTestHttpClientFactory(TestServer server) {
        _testServer = server;
    }

    public override HttpMessageHandler CreateMessageHandler() {
        // TestServer's HttpMessageHandler will be added to the end of the pipeline
        return _testServer.Handler;
    }
}

Factories can be registered globally, but since you need a different TestServer instance for each test, I'd recommend setting it on the FlurlClient instance, which is a new capability as of Flurl.Http 0.7. So your tests would look something like this:

using (var testServer = TestServer.Create(...)) {
    using (var flurlClient = new FlurlClient()) {
        flurlClient.Settings.HttpClientFactory = new OwinTestHttpClientFactory(testServer);

        // do your tests with the FlurlClient instance. 2 ways to do that:
        url.WithClient(flurlClient).PostJsonAsync(...);
        flurlClient.WithUrl(url).PostJsonAsync(...);
    }
}