简体   繁体   English

如何正确模拟我的controllercontext来测试ViewResult.ExecuteResult()?

[英]How can I correctly mock my controllercontext to test ViewResult.ExecuteResult()?

I am attempting to create integration tests to make sure my views do not have any runtime errors in them. 我正在尝试创建集成测试,以确保我的视图中没有任何运行时错误。 Thus I need to create a test that checks if ViewResult.ExecuteResult() works correctly but it seems I have hit a snag. 因此,我需要创建一个测试,检查ViewResult.ExecuteResult()是否正常工作,但似乎我遇到了障碍。

I found this site which gave me a starting point, and I have the following code: 我发现这个网站给了我一个起点,我有以下代码:

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

The problem is that when result.ExecuteResult() is called I get the following exception 问题是当调用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

Unfortunately, that stack trace isn't very useful as I'm not sure what it's trying to access that is null. 不幸的是,这个堆栈跟踪不是很有用,因为我不确定它尝试访问的是null。 Does anyone have any suggestions on how I can create a test for ExecuteResult() ? 有没有人对如何为ExecuteResult()创建测试有任何建议?

Based on the stack trace, it is something in the ViewResultBase.ExecuteResult method that throws the exception. 基于堆栈跟踪,它是ViewResultBase.ExecuteResult方法中抛出异常的东西。 Using reflector, here is the definition of that method: 使用反射器,这是该方法的定义:

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

Based on that code, an object reference exception could be thrown when the code tries to access the RouteData property from the context (if the name of the view wasn't explicitly given to the return type). 基于该代码,当代码尝试从上下文访问RouteData属性时(如果视图的名称未明确赋予返回类型),可能会抛出对象引用异常。

The exception could be thrown by accessing the HttpContext property. 访问HttpContext属性可能会抛出异常。 I haven't used Moq well enough to know if it can handle the fact that you haven't told it how to mock the HttpContext property, but you have told it how to mock the Response property from the HttpContext property's type, so that's another area that is suspect to me. 我没有充分利用Moq知道它是否可以处理你没有告诉它如何模拟HttpContext属性的事实,但是你已经告诉它如何从HttpContext属性的类型模拟Response属性,所以这是另一个我怀疑的地方。

All other uses of context in the method are passing it into other methods, which if those were the problem, then the stack trace would have revealed that. 方法中上下文的所有其他用法都将它传递给其他方法,如果这些方法存在问题,那么堆栈跟踪就会显示出来。

The easiest way to see which of the two I mentioned are the problem, I would write a quick test to pull those properties from your mocks and see which one causes the exception. 看看我提到的两个问题中最简单的方法是问题,我会写一个快速测试来从你的模拟中提取这些属性并查看哪一个导致异常。

I hit the same problem as this just now and resolved it by setting the HttpContext.Current. 我刚刚遇到了同样的问题并通过设置HttpContext.Current来解决它。

Try adding the following to your unit test code: eg 尝试将以下内容添加到您的单元测试代码中:例如

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

One thing that I found useful for debugging this sort of problem rather than using reflector or ILSpy is to turn on debug symbols for the .Net framework code. 我发现调试此类问题而不是使用反射器或ILSpy有用的一件事是打开.Net框架代码的调试符号。 That way you can attach to your NUnit process and see exactly what line of code is throwing the exception and therefore what you need to Mock in the test. 这样你就可以附加到你的NUnit进程,看看究竟是什么行代码抛出了异常,因此你需要在测试中模拟Mock。

Shawn Burke has written an excellent blog article detailing how to set this up here: http://blogs.msdn.com/b/sburke/archive/2008/01/16/configuring-visual-studio-to-debug-net-framework-source-code.aspx Shawn Burke撰写了一篇精彩的博客文章,详细介绍了如何在此处进行设置: http//blogs.msdn.com/b/sburke/archive/2008/01/16/configuring-visual-studio-to-debug-net-框架-源code.aspx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM