在 .NET Core 3.1 中,RequestCookieCollection 不能再用于在单元测试中创建 cookie

Din*_*rdo 11 c# cookies unit-testing asp.net-core-3.1

我刚刚从 .NET Core 2.2 升级到 3.1。我进行了测试以确认我添加的扩展方法HttpContext.Request正在工作。我以前能够做这样的事情:

    var context = new DefaultHttpContext();
    var c = new Dictionary<string, string> {{"test", "passed"}};
    context.Request.Cookies = new RequestCookieCollection(cookies);

    var result = context.Request.GetPrimedValue();
Run Code Online (Sandbox Code Playgroud)

现在这不可能了吗?我尝试为此使用 Moq,但似乎有太多东西阻止我使用任何可用的东西来设置 Cookies 属性。对此有何决议?

注意:我知道这是使用一个不应该是内部的内部类,所以我不反对隐藏内部命名空间,但我不确定我的替代方案是什么。

vic*_*510 15

通过操作一些基础类,我能够生成一个模拟 cookie 集合。然而,它更像是一种解决方法,可能在未来的版本中不起作用。您可能想尝试一下,看看它可以持续多久......

使用辅助功能:

    private static IRequestCookieCollection MockRequestCookieCollection(string key, string value)
    {
            var requestFeature = new HttpRequestFeature();
            var featureCollection = new FeatureCollection();

            requestFeature.Headers = new HeaderDictionary();
            requestFeature.Headers.Add(HeaderNames.Cookie, new StringValues(key + "=" + value));

            featureCollection.Set<IHttpRequestFeature>(requestFeature);

            var cookiesFeature = new RequestCookiesFeature(featureCollection);

            return cookiesFeature.Cookies;
    }
Run Code Online (Sandbox Code Playgroud)

现在你的单元测试代码应该变成

    var context = new DefaultHttpContext();

    context.Request.Cookies = MockRequestCookieCollection("test", "passed");
Run Code Online (Sandbox Code Playgroud)


小智 10

我发现对于我的目的来说,最简单的解决方案是利用 aDictionary<string, string>几乎是IRequestCookieCollection. 只需将该Keys属性公开为ICollection<string>,并覆盖索引器,以便在询问不存在的键时返回 null,而不是抛出:

public class RequestCookieCollection : Dictionary<string, string>, IRequestCookieCollection
{
    public new ICollection<string> Keys => base.Keys;
    public new string this[string key]
    {
        get
        {
            TryGetValue(key, out var value);
            return value;
        }
        set
        {
            base[key] = value;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Son*_*Cue 7

另一种通过附加请求标头来模拟 cookie 的方法。

[TestMethod]
public void Test()
{
    // Arrange
    var controller = new Controller();
    var cookie = new StringValues(COOKIE_NAME + "=" + COOKIE_VALUE);
    controller.ControllerContext = new ControllerContext { HttpContext = new DefaultHttpContext() };
    controller.ControllerContext.HttpContext.Request.Headers.Add(HeaderNames.Cookie, cookie);

    // Act
    var result = Sut.Action();

    // Assert
    // TODO
}
Run Code Online (Sandbox Code Playgroud)


Mat*_*t B 2

抱歉,我无法将其添加为注释,但如果您基于 .net core 代码库中的原始类创建自己的 RequestCookieCollection 类:

https://github.com/dotnet/aspnetcore/blob/4ef204e13b88c0734e0e94a1cc4c0ef05f40849e/src/Http/Http/src/Internal/RequestCookieCollection.cs

Then you could use this new class to create your cookie collection in your unit tests project. I tried this approach and it works.