如何在使用模拟HttpMessageHandler时使用HttpClient管理cookie

And*_*ott 4 mocking httpcookie dotnet-httpclient

我有一个单元测试,通过传入HttpRequestMessage实例和接收HttpResponseMessages实例来调用类库.这与ApiController在这方面测试WebApi非常相似.

我正在测试的代码添加了cookie HttpResponseMessage,并希望在后续的来电中看到这些cookie HttpRequestMessage,这就是浏览器(或HttpWebRequest)的行为方式.

我没有使用,HttpClientHandler因为请求实际上不是在网络上发送,而是使用HttpMessageHandler我初始化HttpClientwith 的模拟传递给产品.因此HttpClientHandler我无法访问cookie处理.似乎要获得我需要的cookie行为,我将不得不手动解析其中的cookie HttpResponseMessage,然后手动将它们序列化为HttpRequestMessage.这完全省略了CookieContainer正确应用cookie到正确请求的逻辑.

有没有更简单的方法?

And*_*ott 6

我写了自己的东西DelegatingHandler,为我管理cookie.我还写了几个扩展方法,CookieContainer以便它可以很容易地使用HttpRequestMessageHttpResponseMessage:

internal class DangerouslySimpleCookieContainer : DelegatingHandler {
    internal DangerouslySimpleCookieContainer(CookieContainer cookieContainer = null) {
        this.Container = cookieContainer ?? new CookieContainer();
    }

    internal DangerouslySimpleCookieContainer(HttpMessageHandler innerHandler, CookieContainer cookieContainer = null)
        : base(innerHandler) {
        this.Container = cookieContainer ?? new CookieContainer();
    }

    public CookieContainer Container { get; set; }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
        this.Container.ApplyCookies(request);
        var response = await base.SendAsync(request, cancellationToken);
        this.Container.SetCookies(response);
        return response;
    }
}

internal static class CookieContainerExtensions {
    internal static void SetCookies(this CookieContainer container, HttpResponseMessage response, Uri requestUri = null) {
        Requires.NotNull(container, "container");
        Requires.NotNull(response, "response");

        IEnumerable<string> cookieHeaders;
        if (response.Headers.TryGetValues("Set-Cookie", out cookieHeaders)) {
            foreach (string cookie in cookieHeaders) {
                container.SetCookies(requestUri ?? response.RequestMessage.RequestUri, cookie);
            }
        }
    }

    internal static void ApplyCookies(this CookieContainer container, HttpRequestMessage request) {
        Requires.NotNull(container, "container");
        Requires.NotNull(request, "request");

        string cookieHeader = container.GetCookieHeader(request.RequestUri);
        if (!string.IsNullOrEmpty(cookieHeader)) {
            request.Headers.TryAddWithoutValidation("Cookie", cookieHeader);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)