我有一个单元测试,通过传入HttpRequestMessage
个实例并接收HttpResponseMessages
个实例来调用类库。这与在这方面测试WebApi ApiController
非常相似。
我正在测试的代码会向HttpResponseMessage
添加Cookie,并期望在后续传入的HttpRequestMessage
调用中看到这些Cookie,这就是浏览器(或HttpWebRequest
)的行为方式
我没有使用HttpClientHandler
因为请求实际上并不在网络上,而是使用我初始化HttpMessageHandler
的模拟HttpClient
传递给产品用。因此,HttpClientHandler
中的cookie处理对我来说是无法访问的。似乎要获得我需要的cookie行为,我将不得不手动解析HttpResponseMessage
中的cookie,然后手动将它们序列化为HttpRequestMessage
。这完全省略了CookieContainer正确应用cookie到正确请求的逻辑。
有更简单的方法吗?
答案 0 :(得分:6)
我写了自己的DelegatingHandler
为我管理Cookie。我还在CookieContainer
上写了几个扩展方法,以便它可以很容易地与HttpRequestMessage
和HttpResponseMessage
一起使用:
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);
}
}
}