我是单元测试我的MVC.Net 4应用程序,我需要一些帮助来测试将视图呈现为字符串。
当我测试视图渲染到字符串崩溃时。
在我的控制器中,我调用以下行来创建要在Json对象中发回的html字符串。
String html = this.RenderPartialViewToString("~/Areas/Admin/Views/Statistics/Graphs/LineGraph.cshtml", orderData);
RenderPartialViewtoString方法如下:
public static string RenderPartialViewToString(this Controller controller, string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
{
viewName = controller.ControllerContext.RouteData.GetRequiredString("action");
}
controller.ViewData.Model = model;
using (var sw = new StringWriter())
{
// Find the partial view by its name and the current controller context.
ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
// Create a view context.
var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
// Render the view using the StringWriter object.
viewResult.View.Render(viewContext, sw);
//viewResult.ViewEngine.ReleaseView(controller.ControllerContext, viewResult.View);
return sw.GetStringBuilder().ToString();
}
}
我正在使用Moq模拟HttpContext。
public static Mock<HttpContextBase> MockHttpContext()
{
var browser = new Mock<HttpBrowserCapabilitiesBase>();
var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();
var response = new Mock<HttpResponseBase>();
var server = new Mock<HttpServerUtilityBase>();
var cookies = new HttpCookieCollection();
var items = new ListDictionary();
var session = new MockHttpSession();
browser.Setup(b => b.IsMobileDevice).Returns(false);
request.Setup(r => r.Cookies).Returns(cookies);
request.Setup(r => r.ValidateInput());
//request.Setup(r => r.UserAgent).Returns("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11");
response.Setup(r => r.Cookies).Returns(cookies);
request.Setup(r => r.Browser).Returns(browser.Object);
//request.Setup(r => r.AppRelativeCurrentExecutionFilePath).Returns("/");
//request.Setup(r => r.ApplicationPath).Returns("/");
request.Setup(x => x.Form).Returns(new NameValueCollection());
response.Setup(s => s.ApplyAppPathModifier(It.IsAny<string>())).Returns<string>(s => s);
response.SetupProperty(res => res.StatusCode, (int)System.Net.HttpStatusCode.OK);
context.Setup(ctx => ctx.Request).Returns(request.Object);
context.Setup(ctx => ctx.Response).Returns(response.Object);
context.Setup(ctx => ctx.Session).Returns(session);
context.Setup(ctx => ctx.Server).Returns(server.Object);
context.Setup(ctx => ctx.Items).Returns(items);
return context;
}
public static Mock<HttpContextBase> MockHttpContext(string url)
{
var context = MockHttpContext();
context.Object.Request.SetupRequestUrl(url);
return context;
}
public class MockHttpSession : HttpSessionStateBase
{
Dictionary<string, object> m_SessionStorage = new Dictionary<string, object>();
public override object this[string name]
{
get {
try
{
return m_SessionStorage[name];
}
catch (Exception)
{
return null;
}
}
set { m_SessionStorage[name] = value; }
}
public override void Remove(string name)
{
m_SessionStorage[name] = null;
}
}
public static void SetMockControllerContext(this Controller controller,
HttpContextBase httpContext = null,
RouteData routeData = null,
RouteCollection routes = null)
{
//If values not passed then initialise
routeData = routeData ?? new RouteData();
routes = routes ?? RouteTable.Routes;
httpContext = httpContext ?? MockHttpContext().Object;
var requestContext = new RequestContext(httpContext, routeData);
var context = new ControllerContext(requestContext, controller);
//Modify controller
controller.Url = new UrlHelper(requestContext, routes);
controller.ControllerContext = context;
}
使用前一个代码块中的方法将模拟上下文添加到控制器。
MvcMockHelpers.SetMockControllerContext(controller,httpContextMock.Object,routeData,routeCollection);
模拟ViewEngine以提供正确的视图:
IEnumerable<string> FileExtensions = new[]
{
"cshtml"
};
IViewPageActivator viewPageActivator = null;
var view = new RazorView(controller.ControllerContext, "Areas/Admin/Views/Statistics/Graphs/LineGraph.cshtml", layoutPath: null, runViewStartPages: false, viewStartFileExtensions: FileExtensions, viewPageActivator: viewPageActivator);
//Mocking View Engine to make sure that the Partial View To String function works.
var engine = new Mock<IViewEngine>();
var viewEngineResult = new ViewEngineResult(view, engine.Object);
engine.Setup(e => e.FindPartialView(It.IsAny<ControllerContext>(), It.IsAny<string>(), It.IsAny<bool>())).Returns(viewEngineResult);
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(engine.Object);
然后我调用控制器动作方法来渲染视图
var result = controller.StatisticsUpdate(model);
我在System.Web.VirtualPath.GetCacheKey()
Stacktrace:
at System.Web.VirtualPath.GetCacheKey()
at System.Web.Compilation.BuildManager.GetCacheKeyFromVirtualPath(VirtualPath virtualPath, Boolean& keyFromVPP)
at System.Web.Compilation.BuildManager.GetVPathBuildResultFromCacheInternal(VirtualPath virtualPath, Boolean ensureIsUpToDate)
at System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate)
at System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate)
at System.Web.Compilation.BuildManager.GetVirtualPathObjectFactory(VirtualPath virtualPath, HttpContext context, Boolean allowCrossApp, Boolean throwIfNotFound)
at System.Web.Compilation.BuildManager.GetVirtualPathObjectFactory(VirtualPath virtualPath, HttpContext context, Boolean allowCrossApp)
at System.Web.Compilation.BuildManager.GetCompiledType(VirtualPath virtualPath)
at System.Web.Compilation.BuildManager.GetCompiledType(String virtualPath)
at System.Web.Mvc.BuildManagerWrapper.System.Web.Mvc.IBuildManager.GetCompiledType(String virtualPath)
at System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer)
at WebUi.Extensions.ControllerExtensions.RenderPartialViewToString(Controller controller, String viewName, Object model) in d:\Element Software\PlasticRepository\Nobastore\WebUi\Extensions\ControllerExtensions.cs:line 37
at WebUi.Areas.Admin.Controllers.OverviewController.StatisticsUpdate(StatisticsModel model) in d:\Element Software\PlasticRepository\Nobastore\WebUi\Areas\Admin\Controllers\OverviewController.cs:line 97
at UnitTests.ControllerTests.Admin.OverviewControllerTest.StatisticsUpdate_View_Test() in d:\Element Software\PlasticRepository\Nobastore\UnitTests\ControllerTests\Admin\OverviewControllerTest.cs:line 147`
我已经尝试了几天搜索源代码,但我无法找到问题,而且我无法在网络上找到任何体面的解决方案。
有人有答案吗?我在模仿httpcontext或controllercontext中遗漏了什么吗?
欢迎任何帮助。