我们有一些控制器操作将面包屑节点的标题更改为用户正在查看的项目的值,例如
[MvcSiteMapNode(Title = "{0}", ParentKey = "Maintenance-Settings-Index", Key = "Maintenance-Settings-Details", PreservedRouteParameters = "id", Attributes = "{\"visibility\":\"SiteMapPathHelper,!*\"}")]
public async Task<ActionResult> Details(int id)
{
var model = await GetSetting(id);
var node = SiteMaps.Current.CurrentNode;
if (node != null)
{
node.Title = string.Format("{0}", model.Name);
}
return View(model);
}
这在正常查看网站时工作正常,并且表现出我们想要的样子..
但是......当尝试使用 Moq 和 FluentMVCTesting 对控制器操作进行单元测试时,我们遇到了错误。
从http://www.shiningtreasures.com/post/2013/08/14/mvcsitemapprovider-4-unit-testing-with-the-sitemaps-static-methods我们添加了SiteMaps.Loader = new Mock<ISiteMapLoader>().Object;
例如
创建控制器上下文
private static ControllerContext FakeControllerContext(RouteData routeData)
{
var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();
var response = new Mock<HttpResponseBase>();
var session = new MockHttpSession();
var server = new Mock<HttpServerUtilityBase>();
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);
var controllerContext = new ControllerContext(context.Object, routeData ?? new RouteData(), new Mock<ControllerBase>().Object);
return controllerContext;
}
为每个测试初始化控制器
[TestInitialize]
public void Initialize()
{
var routeData = new RouteData();
_controller = new DepartmentSettingsController
{
ControllerContext = FakeControllerContext(routeData)
};
}
然后是测试本身
[TestMethod]
public void Details()
{
SiteMaps.Loader = new Mock<ISiteMapLoader>().Object;
_controller.WithCallTo(c => c.Details(_model.Id)).ShouldRenderDefaultView()
.WithModel<SettingViewModel>(m => m.Name == _model.Name);
}
我们收到以下错误System.NullReferenceException:对象引用未设置为对象的实例。指的是var node = SiteMaps.Current.CurrentNode;
然后我们添加另一个测试
[TestMethod]
public void Edit()
{
SiteMaps.Loader = new Mock<ISiteMapLoader>().Object;
_controller.WithCallTo(c => c.Edit(_model.Id)).ShouldRenderDefaultView()
.WithModel<SettingViewModel>(m => m.Name == _model.Name);
}
并获取MvcSiteMapProvider.MvcSiteMapException: 站点地图加载器只能在 Global.asax 的 Application_Start 事件中设置,不得再次设置。如果您使用的是外部依赖注入容器,请将 web.config 文件的 AppSettings 部分中的“MvcSiteMapProvider_UseExternalDIContainer”设置为“true”。在 MvcSiteMapProvider.SiteMaps.set_Loader(ISiteMapLoader 值)
然后SiteMaps.Loader = new Mock<ISiteMapLoader>().Object;
进入测试初始化,例如
[TestInitialize]
public void Initialize()
{
var routeData = new RouteData();
_controller = new DepartmentSettingsController
{
ControllerContext = FakeControllerContext(routeData)
};
SiteMaps.Loader = new Mock<ISiteMapLoader>().Object;
}
我们得到相同的错误MvcSiteMapProvider.MvcSiteMapException: 站点地图加载器只能在 Global.asax 的 Application_Start 事件中设置,不得再次设置。如果您使用的是外部依赖注入容器,请将 web.config 文件的 AppSettings 部分中的“MvcSiteMapProvider_UseExternalDIContainer”设置为“true”。在 MvcSiteMapProvider.SiteMaps.set_Loader(ISiteMapLoader 值)
SiteMaps.Loader = new Mock<ISiteMapLoader>().Object;
问题 -当您测试多个操作时,单元测试中的最佳位置在哪里
问题 - 在控制器中使用静态var node = SiteMaps.Current.CurrentNode;
是最好的方法,还是有更好的方法(我们使用 Unity)
谢谢你的帮助