模拟 ControllerContext.IsChildAction 在 ParentActionViewContext 中抛出异常
Mocking ControllerContext.IsChildAction throws exception in ParentActionViewContext
我在控制器中有一个 ASP.Net MVC 方法:
public ActionResult Update()
{
if(!ControllerContext.IsChildAction)
{
return RedirectToAction("Details","Project");
}
return PartialView();
}
我模拟了 IsChildAction,所以它 return 是真的。
var mockControllerContext = new Mock<ControllerContext>();
mockControllerContext.SetupGet(m => m.IsChildAction).Returns(true);
YourController controller = new YourController();
controller.ControllerContext = mockControllerContext.Object;
但此更改以某种方式反映了 asp.net 机制,该机制现在期望 属性 ControllerContext.ParentActionViewContext 不为空。因此,当在测试中执行 return 语句时,它会抛出 Null 引用,因为此 属性 为空。
我不能嘲笑它,因为它不是虚拟的:/
知道如何为其注入控制器上下文值吗?
您可能必须在 ControllerContext
最小起订量中使用 CallBase = true
:
var mockControllerContext = new Mock<ControllerContext> { CallBase = true, };
这样你仍然可以设置 IsChildAction
属性 但是 CallBase 等于 true ControllerContext
的模拟使用 ControllerContext
的真实实现所以 ParentActionViewContext
应该在那里。
Edit:
在对 mvc-sources 进行简短检查后,我猜 Null-Reference Exception 可能是由来自 this.RouteData.DataTokens["ParentActionViewContext"] as ViewContext;
的 ParentActionViewContext
引起的。
因此请尝试将 fakeRouteData.DataTokens["ParentActionViewContext"] = fakeViewContext;
添加到您的测试中。
这对我有用:
[TestMethod]
public void MyTestMethod()
{
// Arrange
RouteData fakeRouteData = new RouteData();
ViewContext fakeViewContext = new ViewContext();
fakeRouteData.DataTokens["ParentActionViewContext"] = fakeViewContext;
Mock<HttpContextBase> httpContextStub = new Mock<HttpContextBase>();
RequestContext requestContext = new RequestContext(httpContextStub.Object, fakeRouteData);
HomeController controller = new HomeController();
var mockControllerContext = new Mock<ControllerContext>(requestContext, controller) { CallBase = true, };
mockControllerContext.SetupGet(m => m.IsChildAction).Returns(true);
controller.ControllerContext = mockControllerContext.Object;
// Act
var res = controller.Update();
// Assert
// TODO ...
}
测试 System.Web.Mvc,版本=5.2.3.0.
首先从包管理器控制台安装这个包
install-package Xania.AspNet.Simulator -Version 1.3.9
这两个测试是针对Update方法的每个执行路径。
[Test]
public void ChildActionNotInvokedAsChildAction()
{
var action = new TestController()
.Action(c => c.Update());
action.GetActionResult().Should().BeOfType<RedirectToRouteResult>();
}
[Test]
public void ChildActionInvokedAsChildAction()
{
var action = new TestController()
.ChildAction(c => c.Update());
action.GetActionResult().Should().BeOfType<PartialViewResult>();
}
我在控制器中有一个 ASP.Net MVC 方法:
public ActionResult Update()
{
if(!ControllerContext.IsChildAction)
{
return RedirectToAction("Details","Project");
}
return PartialView();
}
我模拟了 IsChildAction,所以它 return 是真的。
var mockControllerContext = new Mock<ControllerContext>();
mockControllerContext.SetupGet(m => m.IsChildAction).Returns(true);
YourController controller = new YourController();
controller.ControllerContext = mockControllerContext.Object;
但此更改以某种方式反映了 asp.net 机制,该机制现在期望 属性 ControllerContext.ParentActionViewContext 不为空。因此,当在测试中执行 return 语句时,它会抛出 Null 引用,因为此 属性 为空。 我不能嘲笑它,因为它不是虚拟的:/
知道如何为其注入控制器上下文值吗?
您可能必须在 ControllerContext
最小起订量中使用 CallBase = true
:
var mockControllerContext = new Mock<ControllerContext> { CallBase = true, };
这样你仍然可以设置 IsChildAction
属性 但是 CallBase 等于 true ControllerContext
的模拟使用 ControllerContext
的真实实现所以 ParentActionViewContext
应该在那里。
Edit:
在对 mvc-sources 进行简短检查后,我猜 Null-Reference Exception 可能是由来自 this.RouteData.DataTokens["ParentActionViewContext"] as ViewContext;
的 ParentActionViewContext
引起的。
因此请尝试将 fakeRouteData.DataTokens["ParentActionViewContext"] = fakeViewContext;
添加到您的测试中。
这对我有用:
[TestMethod]
public void MyTestMethod()
{
// Arrange
RouteData fakeRouteData = new RouteData();
ViewContext fakeViewContext = new ViewContext();
fakeRouteData.DataTokens["ParentActionViewContext"] = fakeViewContext;
Mock<HttpContextBase> httpContextStub = new Mock<HttpContextBase>();
RequestContext requestContext = new RequestContext(httpContextStub.Object, fakeRouteData);
HomeController controller = new HomeController();
var mockControllerContext = new Mock<ControllerContext>(requestContext, controller) { CallBase = true, };
mockControllerContext.SetupGet(m => m.IsChildAction).Returns(true);
controller.ControllerContext = mockControllerContext.Object;
// Act
var res = controller.Update();
// Assert
// TODO ...
}
测试 System.Web.Mvc,版本=5.2.3.0.
首先从包管理器控制台安装这个包
install-package Xania.AspNet.Simulator -Version 1.3.9
这两个测试是针对Update方法的每个执行路径。
[Test]
public void ChildActionNotInvokedAsChildAction()
{
var action = new TestController()
.Action(c => c.Update());
action.GetActionResult().Should().BeOfType<RedirectToRouteResult>();
}
[Test]
public void ChildActionInvokedAsChildAction()
{
var action = new TestController()
.ChildAction(c => c.Update());
action.GetActionResult().Should().BeOfType<PartialViewResult>();
}