我正在尝试对我编写的自定义视图引擎进行单元测试。
视图引擎的预期功能是它改变了执行FindView时RazorViewEngine基本所在的位置
这是我的单元测试
public void ViewEngineReturnsDependencyView()
{
//Mock http request
var mockRequest = new Mock<HttpRequestBase>();
//Mock server variable
NameValueCollection variables = new NameValueCollection();
variables.Add("APPL_PHYSICAL_PATH", TEST_APPLICATION_PATH);
mockRequest.Setup(r => r.ServerVariables).Returns(variables);
//Mock http context
var mockHttpContext = new Mock<HttpContextBase>();
//Mock route
mockHttpContext.Setup(c => c.Request).Returns(mockRequest.Object);
var routeData = new RouteData();
routeData.Values.Add("controller", "testController");
routeData.Values.Add("action", "testAction");
//Mock controller context
var controllerContext = new testController().ControllerContext;
controllerContext.HttpContext = mockHttpContext.Object;
controllerContext.RouteData = routeData;
var mockControllerContext = new ControllerContext(mockHttpContext.Object,
routeData,
new Mock<ControllerBase>().Object);
//Run find view
viewEngine.FindView(mockControllerContext, "TestView", null, false);
}
恼人地viewEngine.FindView(...);
抛出异常:
测试方法......引发异常: System.NullReferenceException:未将对象引用设置为对象的实例。 结果StackTrace:
at System.Web.WebPages.DisplayModeProvider.GetDisplayMode(HttpContextBase context)
at System.Web.Mvc.VirtualPathProviderViewEngine.GetPathFromGeneralName(ControllerContext controllerContext,List`1 locations,String name,String controllerName,String areaName,String cacheKey,String []&searchLocations)
at System.Web.Mvc.VirtualPathProviderViewEngine.GetPath(ControllerContext controllerContext,String [] locations,String [] areaLocations,String locationsPropertyName,String name,String controllerName,String cacheKeyPrefix,Boolean useCache,String []&amp; searchingLocations)< / p>
at System.Web.Mvc.VirtualPathProviderViewEngine.FindView(ControllerContext controllerContext,String viewName,String masterName,Boolean useCache)
at ... Mvc.CustomRazorViewEngine.FindView(ControllerContext controllerContext,String viewName,String masterName,Boolean useCache)in ... \ Mvc \ CustomRazorViewEngine.cs:line 85
at ... Tests.MVC.ViewEngine.ViewEngineReturnsDependencyView()in ... Tests \ MVC \ ViewEngine.cs:第78行
我的问题是,如何创建适当的模拟单元测试RazorViewEngine.FindView()?
答案 0 :(得分:6)
System.Web.WebPages.DisplayModeProvider.GetDisplayMode()
方法正在使用HttpContext.Items
属性,您还需要模拟该属性。
尝试:
mockHttpContext.Setup(c => c.Items).Returns(new Dictionary<object, object>());
答案 1 :(得分:2)
我知道,我可能迟到了,但我遇到了同样的问题。经过一些研究,我发现了微软团队如何测试剃刀引擎的方式。你可以在这里找到它:http://aspnetwebstack.codeplex.com/SourceControl/latest#test/System.Web.Mvc.Test/Test/RazorViewEngineTest.cs 基本思想是创建可测试的视图引擎存根,它明确地公开了视图引擎的受保护方法。 ir称为TestableRazorViewEngine,您可以在文件末尾找到它。我根据自己的需要改变了一下。我在每个存根视图引擎的ControllerContext类型方法中添加了第3个参数,以将控制器元数据传递给我的视图引擎。 这就是我这样做的方式:
[Fact]
public void CreatePartialView_ViewNameWithoutReplacementToken_ReturnsOriginalPath()
{
var engine = new TestableViewEngine();
var view = (RazorView)engine.CreatePartialView("partial path", new ControllerContext());
Assert.Equals("partial path", view.ViewPath);
}
[Fact]
public void CreatePartialView_ViewNameWithReplacementToken_ReturnsViewWithTokenReplacedByControllerNamespace()
{
var engine = new TestableViewEngine();
var controller = new DummyController();
var controllerContext = new ControllerContext { Controller = controller };
var view = (RazorView)engine.CreatePartialView("partial path %1", controllerContext);
Assert.Equals("partial path Stub/Tests/Controllers", view.ViewPath);
}