【问题标题】:How can I correctly mock my controllercontext to test ViewResult.ExecuteResult()?如何正确模拟我的控制器上下文以测试 ViewResult.ExecuteResult()?
【发布时间】:2011-05-17 02:30:07
【问题描述】:

我正在尝试创建集成测试以确保我的视图中没有任何运行时错误。因此,我需要创建一个测试来检查ViewResult.ExecuteResult() 是否正常工作,但似乎我遇到了障碍。

我找到了this site,这给了我一个起点,我有以下代码:

    [TestMethod]
    public void RegisterResultExecutes()
    {
        //arrange 
        RequestContext requestContext = new RequestContext(new MockHttpContext(), new RouteData());
        AccountController controller = new AccountController
        {
            FormsService = new MockFormsAuthenticationService(),
            MembershipService = new MockMembershipService(),
            Url = new UrlHelper(requestContext)
        };

        var result = controller.Register();
        var sb = new StringBuilder();
        Mock<HttpResponseBase> response = new Mock<HttpResponseBase>();
        response.Setup(x => x.Write(It.IsAny<string>())).Callback<string>(y =>
        {
            sb.Append(y);
        });
        Mock<ControllerContext> controllerContext = new Mock<ControllerContext>();
        controllerContext.Setup(x => x.HttpContext.Response).Returns(response.Object);

        //act 
        result.ExecuteResult(controllerContext.Object);
    }

问题是当result.ExecuteResult() 被调用时,我得到以下异常

System.NullReferenceException: Object reference not set to an instance of an object.

System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context)
MyApp.Tests.Controllers.AccountControllerTest.RegisterResultExecutes() in C:\Users\KallDrexx\Documents\Projects\MyApp\MyApp.Tests\Controllers\AccountControllerTests.cs: line 297

不幸的是,该堆栈跟踪不是很有用,因为我不确定它试图访问什么是空的。有人对我如何为ExecuteResult() 创建测试有任何建议吗?

【问题讨论】:

    标签: c# asp.net-mvc asp.net-mvc-3 integration-testing


    【解决方案1】:

    根据堆栈跟踪,是 ViewResultBase.ExecuteResult 方法中的某些内容引发了异常。使用反射器,这是该方法的定义:

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }
        if (string.IsNullOrEmpty(this.ViewName))
        {
            this.ViewName = context.RouteData.GetRequiredString("action");
        }
        ViewEngineResult result = null;
        if (this.View == null)
        {
            result = this.FindView(context);
            this.View = result.View;
        }
        TextWriter output = context.HttpContext.Response.Output;
        ViewContext viewContext = new ViewContext(context, this.View, this.ViewData, this.TempData, output);
        this.View.Render(viewContext, output);
        if (result != null)
        {
            result.ViewEngine.ReleaseView(context, this.View);
        }
    }
    

    根据该代码,当代码尝试从上下文访问 RouteData 属性时,可能会引发对象引用异常(如果视图名称未明确提供给返回类型)。

    访问HttpContext 属性可能会引发异常。我还没有很好地使用起订量,不知道它是否可以处理您没有告诉它如何模拟 HttpContext 属性的事实,但是您已经告诉它如何从 HttpContext 模拟 Response 属性属性的类型,所以这是我怀疑的另一个领域。

    方法中上下文的所有其他用途都将其传递给其他方法,如果这些是问题所在,那么堆栈跟踪就会发现这一点。

    查看我提到的两个中的哪一个是问题的最简单方法是,我会编写一个快速测试从你的模拟中提取这些属性,看看哪个导致异常。

    【讨论】:

    • 啊哈,反射提供了很多信息。是RouteData 导致了这个问题,但现在看来我需要找到一种方法让context.RouteData.GetRequiredString("action"); 返回一些有用的东西,因为这就是我现在卡住的地方
    • 在正确设置RouteData 之后,我似乎已经到了我能做的极限,这似乎是不可能的。对FindView() 的调用在System.Web.Compilation.BuildManager.GetCacheKeyFromVirtualPath() 的堆栈跟踪中获得NullReferenceException 15(字面意思)层。哦,好吧:(
    • 我担心你会遇到这样的表演障碍。您是否正在尝试在您的视图中测试某些特定的东西?如果你想确保你的 lambda 表达式没问题(如果你正在使用),你可以compile your views。如果您想测试 javascript,那么我会在 google 周围搜索 javascript 单元测试,因为我知道那里有框架,但我没有使用任何框架。或者你想一起对其他东西进行单元测试?
    • 我正在尝试创建单元测试,因此我将对任何视图编译错误进行测试时检查(无需每次都编译视图,因为它很慢,或者可能忘记切换配置以编译视图之前推送到生产环境),并检查运行时错误(控制器发送视图不期望的视图模型、无效的强制转换、对助手或操作的错误调用等)。看起来视图是代码将驻留但无法测试的区域,并且有可能隐藏异常/错误,即使在一些简单的视图上也是如此。
    【解决方案2】:

    我刚才遇到了同样的问题,并通过设置 HttpContext.Current 解决了它。

    尝试将以下内容添加到您的单元测试代码中:例如

    HttpContext.Current = new HttpContext(
        new HttpRequest("", "http://mock", ""),
        new HttpResponse(new StringWriter()));
    

    我发现对调试这类问题而不是使用反射器或 ILSpy 有用的一件事是打开 .Net 框架代码的调试符号。这样,您可以附加到您的 NUnit 进程,并准确查看哪行代码引发了异常,因此您需要在测试中模拟什么。

    Shawn Burke 撰写了一篇出色的博客文章,详细介绍了如何在此处进行设置:http://blogs.msdn.com/b/sburke/archive/2008/01/16/configuring-visual-studio-to-debug-net-framework-source-code.aspx

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-01
      • 2021-11-19
      • 2023-03-14
      • 2018-08-15
      • 1970-01-01
      • 2010-09-07
      • 2016-09-22
      • 1970-01-01
      相关资源
      最近更新 更多