在ASP.NET 5/MVC 6上的AspNet.TestHost.TestServer上下文中访问单元测试中的Cookie

poc*_*sov 9 testing cookies owin asp.net-core-mvc asp.net-core

有没有简单的方法来得到一个访问CookieContainerresponse对象中运行集成测试用AspNet.TestHost.TestServer.Cookie必须由控制器操作设置.实现这一目标的最佳方法是什么?

            var client = TestServer.Create(app =>
            {
                app.UseMvc(routes => 
                       routes.MapRoute("default", "{controller}/{action}/{id?}"));
                app.UseIdentity();
            }).CreateClient();

            var request = new HttpRequestMessage(HttpMethod.Get, "account/login");
            var response = await client.SendAsync(request);

            // how to get an access to cookie container ?????????
            // response.Cookies prop doesn't exist
            Assert.NotEmpty(response.Cookies["auth"]);
Run Code Online (Sandbox Code Playgroud)

我看到的解决方案是扩展TestServer的实例,返回类的实例CustomClientHandler : ClientHandler并覆盖在该处理程序中发送请求的整个过程,但除了相对较小的TestServer代码之外,它还需要改变所有逻辑.

有没有更好的建议如何在响应中实现对Cookie的访问?

Mar*_*tin 7

作为 @Oleh 响应的补充,您可以实现相同的目标,而无需反思 .NET 4.6.1+ / .NET Core 等较新的框架

public class TestHttpClientHandler : DelegatingHandler
{
    [NotNull]
    private readonly CookieContainer cookies = new CookieContainer();

    public TestHttpClientHandler([NotNull] HttpMessageHandler innerHandler)
        : base(innerHandler) { }

    [NotNull, ItemNotNull]
    protected override async Task<HttpResponseMessage> SendAsync([NotNull] HttpRequestMessage request, CancellationToken ct)
    {
        Uri requestUri = request.RequestUri;
        request.Headers.Add(HeaderNames.Cookie, this.cookies.GetCookieHeader(requestUri));

        HttpResponseMessage response = await base.SendAsync(request, ct);

        if (response.Headers.TryGetValues(HeaderNames.SetCookie, out IEnumerable<string> setCookieHeaders))
        {
            foreach (SetCookieHeaderValue cookieHeader in SetCookieHeaderValue.ParseList(setCookieHeaders.ToList()))
            {
                Cookie cookie = new Cookie(cookieHeader.Name.Value, cookieHeader.Value.Value, cookieHeader.Path.Value);
                if (cookieHeader.Expires.HasValue)
                {
                    cookie.Expires = cookieHeader.Expires.Value.DateTime;
                }
                this.cookies.Add(requestUri, cookie);
            }
        }

        return response;
    }
}
Run Code Online (Sandbox Code Playgroud)


Ole*_*ilo 5

我已经实现了跟踪 cookie 的自定义 HttpMessageHandler。

它使用反射来调用实际的处理程序并仅读取/设置 Cookie 标头。

class TestMessageHandler : HttpMessageHandler
{
    delegate Task<HttpResponseMessage> HandlerSendAsync(HttpRequestMessage message, CancellationToken token);

    private readonly HandlerSendAsync nextDelegate;
    private readonly CookieContainer cookies = new System.Net.CookieContainer();

    public TestMessageHandler(HttpMessageHandler next)
    {
        if(next == null) throw new ArgumentNullException(nameof(next));

        nextDelegate = (HandlerSendAsync)
                            next.GetType()
                                .GetTypeInfo()
                                .GetMethod("SendAsync", BindingFlags.NonPublic | BindingFlags.Instance)
                                .CreateDelegate(typeof(HandlerSendAsync), next);
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        request.Headers.Add("Cookie", cookies.GetCookieHeader(request.RequestUri));

        var resp = await nextDelegate(request, cancellationToken).ConfigureAwait(false);

        if (resp.Headers.TryGetValues("Set-Cookie", out var newCookies))
        {
            foreach (var item in SetCookieHeaderValue.ParseList(newCookies.ToList()))
            {
                cookies.Add(request.RequestUri, new Cookie(item.Name, item.Value, item.Path));
            }
        }

        return resp;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你像这样创建 HttpClient:

var httpClient = new HttpClient(
                     new TestMessageHandler(
                         server.CreateHandler()));
Run Code Online (Sandbox Code Playgroud)

TestMessageHandler 现在负责跟踪 cookie。