代码之家  ›  专栏  ›  技术社区  ›  Dean Taylor

单元测试或运行时ActionResult字符串通过ExecuteResult输出响应?

  •  5
  • Dean Taylor  · 技术社区  · 14 年前

    问题。。。

    单元测试的最佳方法是什么 字符串响应 内容类型 从几种控制器方法?

    使用。。。

    每个方法返回一个 ActionResult ,其中一些是 ViewResult 响应。我正在使用ASP.NET MVC 2型 RTM和 最小起订量 .

    明确地。。。

    我想得到 TextWriter HttpContext.Response 并使其包含来自 行动结果 .

    为什么?

    一。单元测试内

    我想测试一些特定的if内容 没有 与输出一起存在。

    2。通过工作线程运行时

    我使用后台工作线程更新远程服务器上的静态内容,此内容是控制器的输出,必须按此方式生成。不建议通过HTTP向同一服务器发出请求,因为有许多1000个文件正在更新。

    我看到在这两处都使用了相同的代码 运行时 和via 单元测试 ,因为它会非常相似?

    绊脚石1

    如何正确设置模拟以不需要路由 或者 呼叫 RegisterRoutes RegisterAllAreas 如果调用成功,当前将在内部引发异常 BuildManagerWrapper::IBuildManager.GetReferencedAssemblies .

    示例代码

    我的嘲笑助手看起来是这样的:

    public static HttpContextBase FakeHttpContext()
    {
        var context = new Mock<HttpContextBase>();
        var request = new Mock<HttpRequestBase>();
        var response = new Mock<HttpResponseBase>();
        var session = new Mock<HttpSessionStateBase>();
        var server = new Mock<HttpServerUtilityBase>();
        var writer = new StringWriter();
    
        var form = new NameValueCollection();
        var queryString = new NameValueCollection();
        request.Setup(r => r.Form).Returns(form);
        request.Setup(r => r.QueryString).Returns(queryString);
    
        context.Setup(ctx => ctx.Request).Returns(request.Object);
        context.Setup(ctx => ctx.Response).Returns(response.Object);
        context.Setup(ctx => ctx.Session).Returns(session.Object);
        context.Setup(ctx => ctx.Server).Returns(server.Object);
        context.Setup(ctx => ctx.Response.Output).Returns(writer);
    
        return context.Object;
    }
    
    public static void SetFakeControllerContext(this Controller controller)
    {
        var httpContext = FakeHttpContext();
        var routeData = new RouteData();
        var routeData = RouteTable.Routes.GetRouteData(httpContext);
        ControllerContext context = new ControllerContext(new RequestContext(httpContext, routeData), controller);
        controller.ControllerContext = context;
    }
    

    我目前对TestMethod的尝试如下:

    [TestMethod]
    public void CodedJavaScriptAction_Should_Return_JavaScript_Response()
    {
        // Arrange
        var controller = new CodedController();
        controller.SetFakeControllerContext();
    
        // Act
        var result = controller.CodedJavaScript(); // Response is made up as a ViewResult containing JavaScript.
        var controllerContext = controller.ControllerContext;
        var routeData = controllerContext.RouteData;
        routeData.DataTokens.Add("area", "Coded");
        routeData.Values.Add("area", "Coded");
        routeData.Values.Add("controller", "Coded");
        routeData.Values.Add("action", "CodedJavaScript");
    
        var response = controllerContext.HttpContext.Response;
        response.Buffer = true;
        var vr = result as ViewResult;
        vr.MasterName = "CodedJavaScript";
    
        result.ExecuteResult(controllerContext);
    
        // Assert
        var s = response.Output.ToString();
        Assert.AreEqual("text/javascript", response.ContentType);
        Assert.IsTrue(s.Length > 0);
        // @todo: Further tests to be added here.   
    
    }
    

    我的区域、视图和共享文件是:

    - Areas\Coded\Controllers\CodeController.cs
    - Areas\Coded\Views\Coded\CodedJavaScript.aspx
    - Areas\Coded\CodedAreaRegistration.cs
    - Views\Shared\CodedJavaScript.Master

    编辑 :编辑为现在包括单元测试和运行时执行。感谢@Darin Dimitrov提到 集成测试 但现在这个问题还有一个运行时元素。

    编辑 :在使用来自 MvcIntegrationTestFramework as referenced by alexn . 使用 AppDomain.CreateDomain SimpleWorkerRequest 要创建新请求,我发现在已经有活动请求的进程中,无法通过此方法创建新请求,原因是 static 使用的值。所以这就排除了这种方法。

    可能是同一个问题,但我现在想知道的是 局部视图 可以更直接地作为字符串返回吗?

    2 回复  |  直到 7 年前
        1
  •  3
  •   Darin Dimitrov    14 年前

    您要实现的不再是单元测试,而是集成测试,因为您不再孤立地测试应用程序组件,而且有很多优秀的工具允许您这样做 Selenium Web Tests 在Visual Studio的最终版本中。

    这些测试的优点是它们模拟用户请求并覆盖整个应用程序行为。因此,对于给定的用户请求,可以断言应用程序响应正确。其思想是编写用户场景,记录它们,然后可以自动执行这些测试,以断言应用程序按指定的方式响应。

        2
  •  2
  •   alexn    14 年前

    我用史蒂文·桑德森 MvcIntegrationTestFramework 取得了巨大的成功。它很容易使用。

    有了这个,你可以很容易地测试输出响应, 视图数据 ,cookies,session等等,只需很少的努力。

    您将使用如下所示的测试测试呈现的HTML:

    [Test]
    public void Output_Contains_String()
    {
        appHost.SimulateBrowsingSession(session => {
            var result = session.ProcessRequest("/");
            Assert.IsTrue(result.ResponseText.Contains("string to check for"));
        });
    }
    

    没有模拟和路由注册。非常干净。

    由于这在技术上是一个集成测试,因此需要一些时间来设置和运行。

    如果你需要更多的例子或信息,请告诉我。