我正在尝试创建集成测试,以确保我的视图中没有任何运行时错误。因此,我需要创建一个测试,检查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
不幸的是,该堆栈跟踪不是很有用,因为我不确定它尝试访问的是null。有没有人对如何为ExecuteResult()
创建测试提出任何建议?
答案 0 :(得分: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);
}
}
基于该代码,当代码尝试从上下文访问RouteData
属性时(如果视图的名称未明确赋予返回类型),可能会抛出对象引用异常。 / p>
访问HttpContext
属性可能会引发异常。我没有充分利用Moq知道它是否可以处理你没有告诉它如何模拟HttpContext
属性这一事实,但是你告诉它如何模拟Response
属性HttpContext
属性的类型,这是我怀疑的另一个区域。
方法中上下文的所有其他用法都将它传递给其他方法,如果这些方法存在问题,那么堆栈跟踪就会显示出来。
最简单的方法是看看我提到的两个问题中的哪一个是问题,我会写一个快速测试从你的模拟中提取这些属性,看看哪一个导致异常。
答案 1 :(得分:1)
我刚刚遇到了同样的问题,并通过设置HttpContext.Current来解决它。
尝试将以下内容添加到您的单元测试代码中:例如
HttpContext.Current = new HttpContext(
new HttpRequest("", "http://mock", ""),
new HttpResponse(new StringWriter()));
我发现调试此类问题而不是使用反射器或ILSpy有用的一件事是打开.Net框架代码的调试符号。这样你就可以附加到你的NUnit进程,看看究竟是什么行代码抛出了异常,因此你需要在测试中模拟Mock。
Shawn Burke撰写了一篇精彩的博客文章,详细介绍了如何在此处进行设置:http://blogs.msdn.com/b/sburke/archive/2008/01/16/configuring-visual-studio-to-debug-net-framework-source-code.aspx