【问题标题】:MVC 3 Unit Test - Get Actual Response DataMVC 3 单元测试 - 获取实际响应数据
【发布时间】:2011-05-12 18:30:48
【问题描述】:

全部,

我正在使用 ASP.NET MVC 3 开发和单元测试一个交互式语音应用程序,其控制器返回包含 VoiceXML 的视图。我想创建捕获实际 VoiceXML 输出的单元测试,以便对其进行架构验证。

我的阅读和测试将我带到了 Scott H 的使用 Moq 的 FakeHttpContext,以及这里的几个回复。一切都正确编译,我正在尝试执行以下操作:

[TestMethod]
public void WelcomeTest1()
{
     EmergencyController controller = new EmergencyController();
     controller.ControllerContext = new  ControllerContext(MvcMockHelpers.FakeHttpContext("~/Emergency/Welcome"), new RouteData(), controller);

     ViewResult result = (controller.Welcome()) as ViewResult;
 .
 .
     Assert.IsTrue(controller.ControllerContext.HttpContext.Response.OutputStream.Length > 0);
     // assert schema validation on the output here
}

但是,逐步执行此操作,我可以看到正在调用 Welcome 视图,但我正在 Response.Output 中查找某些内容,但没有找到任何内容。模拟设置如下,希望将 CallBase 设置为 true 会真正写出一些东西。我发现了一些我添加到 FakeHttpContext 构造函数中的代码,据说它调用了 StringWriter,但无济于事:

public static HttpContextBase FakeHttpContext()
{
    var context = new Mock<HttpContextBase>();
    var request = new Mock<HttpRequestBase>() { CallBase = true };
    var response = new Mock<HttpResponseBase>();
    var session = new Mock<HttpSessionStateBase>();
    var server = new Mock<HttpServerUtilityBase>();

    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);
    response.Setup(r => r.OutputStream).Returns(new MemoryStream());
    response.Setup(r => r.Headers).Returns(new NameValueCollection());           

    var writer = new StringWriter();
    var wr = new SimpleWorkerRequest("", "", "", "", writer);        
    HttpContext.Current = new HttpContext(wr);

    return context.Object;
}

我确定我遗漏了一些明显的东西,但我现在很难过。

谢谢

吉姆·斯坦利

黑板连接

【问题讨论】:

    标签: unit-testing asp.net-mvc-3 moq


    【解决方案1】:

    结果不会填充到 ViewResult 中。换句话说,视图不是通过您在控制器中调用 return View() 来呈现的,而是 mvc 获取视图结果并稍后在请求系统中呈现它。您需要做的是为 ViewResults 创建一个渲染函数,如下所示:

    using System;
    using System.IO;
    using System.Web.Mvc;
    
    namespace CoPrice.Helpers
    {
        public static class ViewRendrer
        {
            public static string ToHtml(this ViewResult result, Controller controller)
            {
                controller.ViewData.Model = result.Model;
                try
                {
                    using (StringWriter sw = new StringWriter())
                    {
                        ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, result.ViewName);
                        ViewContext context = new ViewContext(controller.ControllerContext, viewResult.View, result.ViewData, result.TempData, sw);
                        viewResult.View.Render(context, sw);
    
                        return sw.GetStringBuilder().ToString();
                    }
                }
                catch (Exception e)
                {
                    return e.ToString();
                }
            }
        }
    }
    

    然后您可以执行 result.ToHtml(controller) 来获取实际数据(我认为这仅适用于 RazorViews,虽然我不确定,但至少我已经使用它了)。

    【讨论】:

    • 嗯,差不多 - 但由于控制器上下文为空,以下代码会爆炸:[TestMethod] public void WelcomeTest1() { EmergencyController controller = new EmergencyController(); ViewResult 结果 = (controller.Welcome()) as ViewResult;字符串 xml = ViewRenderer.ToHtml(结果,控制器);断言.IsTrue(xml.Length > 0);我还尝试从我访问过的其他一些地方添加 FakeControllerContext() 代码,但它也会爆炸,因为控制器上下文的 RouteData() 部分只是一个新的 RouteData()。
    • 哦,对了。我也遇到过这个问题......如果我没记错的话,你需要大量的嘲笑才能让它全部工作,但这确实是可能的。我没有代码,也没有重写它的意愿/时间(对不起),因为这是很多工作,但如果你做一些谷歌搜索,你可能会找到答案。我在你看到的我的控制器中使用了这个 ToHtml 函数,它在那里工作正常。
    • 谢谢。我怀疑(希望)RouteValues() 将是我需要的最后一件事。希望我可以从应用程序中获取实际的路由值。 非常感谢的扩展方法 - 总是能增加我的知识。
    • 没问题。我也是前几天在网上找到的,虽然我不记得在哪里xD。认为这里没有堆栈溢出,我只是用谷歌搜索了我认为的剃刀视图的渲染。
    猜你喜欢
    • 2018-09-08
    • 1970-01-01
    • 1970-01-01
    • 2018-02-21
    • 2014-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-12
    相关资源
    最近更新 更多