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

Kal*_*exx 6 c# asp.net-mvc integration-testing asp.net-mvc-3

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

我发现这个网站给了我一个起点,我有以下代码:

    [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);
    }
Run Code Online (Sandbox Code Playgroud)

问题是,当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
Run Code Online (Sandbox Code Playgroud)

不幸的是,这个堆栈跟踪不是很有用,因为我不确定它尝试访问的是null.有没有人对如何创建测试有任何建议ExecuteResult()

Bri*_*all 4

根据堆栈跟踪,是方法中的某些内容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);
    }
}
Run Code Online (Sandbox Code Playgroud)

基于该代码,当代码尝试从上下文访问RouteData属性时(如果未将视图名称显式指定给返回类型),可能会引发对象引用异常。

可以通过访问该属性来引发异常HttpContext。我还没有很好地使用 Moq,不知道它是否可以处理您没有告诉它如何模拟该HttpContext属性的事实,但您已经告诉它如何ResponseHttpContext属性的类型模拟该属性,所以这是另一个领域对我怀疑。

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

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