【问题标题】:MOQ - Mocking MVC Controller's Response.Cookies.Clear()MOQ - 模拟 MVC 控制器的 Response.Cookies.Clear()
【发布时间】:2013-08-07 08:38:02
【问题描述】:

我是 MOQ 的新手,但我将它与 NUnit 一起用于单元测试。

我已经模拟了我的控制器的所有部分,除了以下行会引发“对象未设置为对象的实例”错误消息。

Response.Cookies.Clear();

我有以下扩展方法来模拟控制器上下文,它适用于我迄今为止遇到的所有其他事情(非常感谢这个论坛上的好人)。

public static int SetUpForTest(this System.Web.Mvc.Controller ctl, string username, TestingUtility.Roles role)
    {
        var routes = new RouteCollection();
        MvcApplication.RegisterRoutes(routes);

        var request = new Mock<HttpRequestBase>(MockBehavior.Strict);
        request.SetupGet(x => x.ApplicationPath).Returns("/");
        request.SetupGet(x => x.Url).Returns(new Uri("http://localhost/a", UriKind.Absolute));
        request.SetupGet(x => x.ServerVariables).Returns(new System.Collections.Specialized.NameValueCollection());

        var response = new Mock<HttpResponseBase>(MockBehavior.Strict);
        response.Setup(x => x.ApplyAppPathModifier(Moq.It.IsAny<String>())).Returns((String url) => url);
        // response.SetupGet(x => x.Cookies).Returns(new HttpCookieCollection()); // This also failed to work

        var context = new Mock<HttpContextBase>(MockBehavior.Strict);
        context.SetupGet(x => x.Request).Returns(request.Object);
        context.SetupGet(x => x.Response).Returns(response.Object);
        context.SetupGet(x => x.Response.Cookies).Returns(new HttpCookieCollection()); // still can't call the Clear() method

        //
        // Mock the controller context (using the objects mocked above)
        //
        var moqCtx = new Mock<ControllerContext>(context.Object, new RouteData(), ctl);
        moqCtx.SetupGet(p => p.HttpContext.User.Identity.Name).Returns(username);
        moqCtx.SetupGet(p => p.HttpContext.User.Identity.IsAuthenticated).Returns(true);
        if (!string.IsNullOrEmpty(role.ToString()))
            moqCtx.Setup(p => p.HttpContext.User.IsInRole(role.ToString())).Returns(true);

        //
        // Pass the mocked ControllerContext and create UrlHelper for the controller and return
        //
        ctl.ControllerContext = moqCtx.Object;
        ctl.Url = new UrlHelper(new RequestContext(context.Object, new RouteData()), routes);
        return 1;
    }

正如您在上面看到的,我试图模拟 cookie 集合的“获取”,但没有帮助。

另外,不能模拟实际的 Clear() 方法,因为它不是虚拟方法。

显然我不想测试 cookie 是否被清除,我只想能够在测试中忽略它。

谢谢,

格雷格

【问题讨论】:

  • 你有没有看到这个问题:stackoverflow.com/questions/1228179/…
  • 感谢您的回复,但我查看了链接中的示例,在上面的控制器上下文的模拟中我没有看到任何我没有做过的事情。如果我遗漏了什么,请指出正确的方向!
  • 您确定在该部分代码中获得的是模拟上下文而不是 HttpContext.Current(例如)吗?只是想知道可能出了什么问题。

标签: c# asp.net-mvc nunit moq


【解决方案1】:

当我执行 cookies.Clear() 时,这对我有用

            var request = new Mock<HttpRequestBase>(MockBehavior.Strict);
        request.SetupGet(x => x.ApplicationPath).Returns("/");
        request.SetupGet(x => x.Url).Returns(new Uri("http://localhost/a", UriKind.Absolute));
        request.SetupGet(x => x.ServerVariables).Returns(new System.Collections.Specialized.NameValueCollection());

        var response = new Mock<HttpResponseBase>(MockBehavior.Strict);
        response.Setup(x => x.ApplyAppPathModifier(Moq.It.IsAny<String>())).Returns((String url) => url);
        // response.SetupGet(x => x.Cookies).Returns(new HttpCookieCollection()); // This also failed to work

        var context = new Mock<HttpContextBase>(MockBehavior.Strict);
        context.SetupGet(x => x.Request).Returns(request.Object);
        context.SetupGet(x => x.Response).Returns(response.Object);
        context.SetupGet(x => x.Response.Cookies).Returns(new HttpCookieCollection()); // still can't call the Clear() method
        context.SetupGet(p => p.User.Identity.Name).Returns("blah");
        context.SetupGet(p => p.User.Identity.IsAuthenticated).Returns(true);

        var rc = new RequestContext(context.Object, new RouteData());

        controller.ControllerContext = new ControllerContext(rc, controller);

【讨论】:

  • 谢谢 - 解决方案是只模拟 HttpContextBase 而不是 ControllerContext 如您在示例中所示。还要感谢 Halvard 的回答,为我指明了正确的方向
【解决方案2】:

在不使用 ActionContext 的情况下引用以前的问题和准确的解决方案:如何使用 ASP.NET 5 (MVC 6) 中的 Response 属性对控制器操作进行单元测试? [重复]

Mocking HttpResponse, HttpContext 很难,因为它们只是只读类型。因此,要模拟这些,请在 HttpResponse 和 HttpContext 上使用 SetupGet,然后将 HttpContext 引用传递给 ControllerContext。

    var headerDict = new HeaderDictionary();
    var httpResponse = new Mock<HttpResponse>();
    var httpContext = new Mock<HttpContext>();
    
    
    httpRespnse.SetupGet(=>c.Headers).Returns(headerDict);
    httpContext.SetupGet(=>c.Response).Returns(httpResponse.Object);

    var controllerContext = new ControllerContext()
   {
       HttpContext = httpContext.Object
   };

    var controllerInstance = new ValueController()
   {
       ControllerContext = controllerContext
   };

【讨论】:

    【解决方案3】:

    (这只是一半的答案,但对于评论字段来说太大了......)

    你对new HttpCookieCollection()的嘲讽是正确的。这段代码分开工作:

    var request = new Mock<HttpRequestBase>(MockBehavior.Strict);
    request.SetupGet(x => x.ApplicationPath).Returns("/");
    request.SetupGet(x => x.Url).Returns(new Uri("http://localhost/a", UriKind.Absolute));
    request.SetupGet(x => x.ServerVariables).Returns(new System.Collections.Specialized.NameValueCollection());
    
    var response = new Mock<HttpResponseBase>(MockBehavior.Strict);
    response.Setup(x => x.ApplyAppPathModifier(Moq.It.IsAny<String>())).Returns((String url) => url);
    // response.SetupGet(x => x.Cookies).Returns(new HttpCookieCollection()); // This also failed to work
    
    var context = new Mock<HttpContextBase>(MockBehavior.Strict);
    context.SetupGet(x => x.Request).Returns(request.Object);
    context.SetupGet(x => x.Response).Returns(response.Object);
    context.SetupGet(x => x.Response.Cookies).Returns(new HttpCookieCollection()); // still can't call the Clear() method
    
    
    // Here clearing the cookies works just fine:
    var instance = context.Object;
    instance.Response.Cookies.Clear();
    

    所以错误不存在,而是其他地方。如果您从代码中注释掉带有Response.Cookies.Clear() 的行会怎样?那么其他所有东西都被正确地嘲笑了吗?当您调试测试时,您是否可以看到 mock 的其余部分是否符合预期?如果是这样,我会感到惊讶(但我之前一直很惊讶......)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-13
      • 1970-01-01
      • 1970-01-01
      • 2015-02-13
      • 1970-01-01
      • 2014-12-03
      • 2011-06-15
      • 1970-01-01
      相关资源
      最近更新 更多