【问题标题】:In .NET Core 3.1, the RequestCookieCollection can no longer be used to create cookies in unit tests在 .NET Core 3.1 中,RequestCookieCollection 不能再用于在单元测试中创建 cookie
【发布时间】:2021-11-24 02:53:06
【问题描述】:

我刚刚从 .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();

现在不可能吗?我尝试为此使用 Moq,但似乎有太多事情阻止我使用任何可用的东西设置 Cookies 属性。解决方法是什么?

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

【问题讨论】:

  • 然后模拟IRequestCookieCollection接口并设置预期的行为
  • 请阅读整篇文章。这似乎需要大量的代码来设置所有内容,因为我在授权过程中使用它,并且似乎有很多检查只是为了确保您正在创建的 cookie 集合甚至可以用于设置cookie 属性。当我为此使用模拟并尝试设置 cookies 属性时,有很多验证失败,因此永远不会设置 cookies 属性。
  • @Dinerdo,你碰巧解决了这个问题吗?我也一直在寻找解决方案。
  • 不幸的是,我暂时忽略了这些测试。 :(
  • 我在这里遇到了完全相同的限制。那件事现在根本不可嘲笑。模拟所有东西所需的时间,如果周围的所有东西都经过测试,可能不会花时间......这真是太糟糕了。

标签: c# unit-testing cookies asp.net-core-3.1


【解决方案1】:

通过操作一些基础类,我能够生成一个模拟 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;
    }

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

    var context = new DefaultHttpContext();

    context.Request.Cookies = MockRequestCookieCollection("test", "passed");

【讨论】:

    【解决方案2】:

    另一种通过附加请求标头来模拟 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
    }
    

    【讨论】:

      【解决方案3】:

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

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

      然后您可以使用这个新类在您的单元测试项目中创建您的 cookie 集合。我尝试了这种方法,它很有效。

      【讨论】:

        【解决方案4】:

        我发现就我的目的而言,最简单的解决方案是利用Dictionary&lt;string, string&gt; 几乎是IRequestCookieCollection 的完整实现这一事实。只需要将Keys 属性公开为ICollection&lt;string&gt;

        public class RequestCookieCollection : Dictionary<string, string>, IRequestCookieCollection
        {
            public new ICollection<string> Keys => base.Keys;
        }
        

        【讨论】:

          【解决方案5】:

          @Victor6510 的回答对我很有用,直到我需要创建一个包含 JSON 的假 cookie。然后我遇到了这个错误:https://github.com/dotnet/aspnetcore/issues/29304 所以我不得不想出其他方法。

          使用 NSubstitute:

          [TestClass]
          public class ImpersonationMiddlewareTest
          {
              private HttpContext _sHttpContext;
              private HttpRequest _sHttpRequest;
              private IRequestCookieCollection _sCookieCollection;
          
              [TestInitialize]
              public void Initialize()
              {
                  _sHttpContext = Substitute.For<HttpContext>();
                  _sHttpRequest = Substitute.For<HttpRequest>();
                  _sCookieCollection = Substitute.For<IRequestCookieCollection>();
              }
          
              [TestMethod]
              public async Task Invoke_GoodCookie_CreatesImpersonationIdentity()
              {
                  //arrange
                  var cookieList = new List<KeyValuePair<string, string>>
                  {
                      new KeyValuePair<string,string>("cookiename", "cookievalue")
                  };
                  _sCookieCollection.GetEnumerator().Returns(e => cookieList.GetEnumerator());
                  _sCookieCollection.ContainsKey("cookiename").Returns(true);
          
                  _sHttpRequest.Cookies.Returns(_sCookieCollection);
          
                  _sHttpContext.Request.Returns(_sHttpRequest);
          
                  //act
                  myMiddleware.InvokeAsync(_sHttpContext);
          
                  //assert
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-10-22
            • 1970-01-01
            • 2020-07-30
            • 2017-04-25
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多