MVC 3 单元测试 - 获取实际响应数据

发布于 2024-11-06 15:26:58 字数 1949 浏览 0 评论 0原文

所有,

我正在使用 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;
}

我确信我错过了一些明显的东西,但我现在很困惑。

感谢

吉姆·斯坦利

Blackboard Connect

All,

I'm developing and unit testing an interactive voice application using ASP.NET MVC 3 whose controllers return Views containing VoiceXML. I'd like to create unit tests that capture the actual VoiceXML output so I can schema-validate it.

My reading and testing have taken me to Scott H's FakeHttpContext that uses Moq, as well as several responses here. Everything compiles correctly, and I'm trying to do something like the following:

[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
}

However, stepping through this, I can see that the Welcome view being called, but I'm looking for something in the Response.Output and not finding anything. The mock is set up as follows, in hope that setting CallBase to true would actually write something out. I found some code that I added to the FakeHttpContext constructor that supposedly invokes a StringWriter, but to no avail:

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;
}

I'm sure I'm missing something obvious, but I'm stumped right now.

Thanks

Jim Stanley

Blackboard Connect

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

‘画卷フ 2024-11-13 15:26:58

结果不会填充到 ViewResult 中。换句话说,视图不是通过在控制器中调用 return View() 来渲染的,而是 mvc 获取 viewresult 并稍后在请求周期中渲染它。您需要做的是为 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,尽管我不确定,至少我就是这么用的)。

The result doesn't get populated in the ViewResult. In other words, the view isn't rendered by you calling return View() in your controller, rather mvc takes the viewresult and renders it at a later time in the request-sycle. What you need to do is to create a render-function for ViewResults, like this one:

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();
            }
        }
    }
}

Then you can do result.ToHtml(controller) to get the actual data (this works for RazorViews only I think, though I'm not sure, that's what I've used it for at least).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文