模拟 HttpClient 和 send/get cookie 的正确方法

Proper way to mock HttpClient and send/get cookies

我正在使用 moq 模拟我为 HttpClient 创建的包装器 class:

public interface IHttpClientWrapper
{
    Task<HttpResponseMessage> PostAsync(Uri uri,
                                        HttpContent content,
                                        CookieContainer cookies = null);
}

在我 "normal" 实现 PostAsync 中,我只是将调用委托给 HttpClient

public Task<HttpResponseMessage> PostAsync(Uri uri, HttpContent content, CookieContainer cookies = null)
{
    var client = cookies == null ? new HttpClient()
        : new HttpClient(new HttpClientHandler { CookieContainer = cookies });

    return client.PostAsync(uri, content);
}

所以,在我的应用程序中,一切正常,我得到了服务器设置的 cookie(cookies.Count 不是 0

为了我的测试,我有一个 Mock<IHttpClientWrapper>,我已经将它的 PostAsync 方法设置为 return 和 new HttpResponseMessage。我还调用 HttpResponseMessage.Headers.AddCookies 方法向此响应添加 2 个 cookie。

但是当我以这样的方式调用我的模拟 object 时:

/* I setup url and content */
var mock = new Mock<IHttpClientHelper>();
mock.Setup(/* setup PostAsync to return the response I create */)...
var cookies = new CookieContainer();
var response = await mock.PostAsync(url, content, cookies);

那么,cookies.Count 总是 0

所以,我想知道与调用实际服务器有什么不同?我需要额外的 headers 吗?我如何在这里设置cookies?

CookieContainer 作为参数传递给 PostAsync 方法。 PostAsync 将 cookie 添加到 CookiesContainer 这一事实是此方法的 副作用 特殊 IHttpClientHelper 实施。 new Mock<IHttpClientHelper> 创建 另一个 不添加 cookie 的实现。

因此,如果您希望 mock 将 cookie 添加到容器中,则需要额外的设置

mock.Setup(_ => _.PostAsync(It.IsAny<Uri>(), It.IsAny<HttpContent>(), It.IsAny<CookieContainer>()))
    .Callback<Uri, HttpContent, CookieContainer>((u, c, cookieContainer) => 
    {
        // Add required cookies here
        cookieContainer.Add(...);
    });

CallbackMock 设置副作用的方法。