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

时间:2013-03-23 14:59:18

标签: mocking httpcookie dotnet-httpclient

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

我正在测试的代码会向HttpResponseMessage添加Cookie,并期望在后续传入的HttpRequestMessage调用中看到这些Cookie,这就是浏览器(或HttpWebRequest)的行为方式

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

有更简单的方法吗?

1 个答案:

答案 0 :(得分: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);
        }
    }
}