如何测试我的asp.net-mvc控制器的OnActionExecuting方法?
我重写了我的控制器的OnActionExecuting方法,根据执行的filterContext设置一些内部状态。我如何测试这个?该方法本身是受保护的,所以我认为我必须在调用堆栈中更高。如何测试我的asp.net-mvc控制器的OnActionExecuting方法?
我需要测试什么代码?
我使用MVC RC 1
编辑:我也使用NUnit。
谢谢
您需要添加和使用一个专用访问器。右键单击您的控制器类,然后从菜单中选择Create Private Accessors
并将它们添加到您的测试项目中。一旦进入您的测试项目,创建您的控制器,然后为其创建一个访问器。该方法应该在访问器上可用。下面是我自己的代码进行了抽样检测:
/// <summary>
///A test for OnActionExecuting
///</summary>
[TestMethod()]
[ExpectedException(typeof(InvalidOperationException))]
public void OnActionExecutingWindowsIdentityTest()
{
var identity = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(identity);
var httpContext = MockRepository.GenerateStub<HttpContextBase>();
httpContext.User = principal;
var actionDescriptor = MockRepository.GenerateStub<ActionDescriptor>();
RouteData routeData = new RouteData();
BaseController controller = new BaseController();
BaseController_Accessor accessor = new BaseController_Accessor(new PrivateObject(controller));
ControllerContext controllerContext = MockRepository.GenerateStub<ControllerContext>(httpContext, routeData, controller);
ActionExecutingContext filterContext = new ActionExecutingContext(controllerContext, actionDescriptor, new Dictionary<string, object>());
accessor.OnActionExecuting(filterContext);
}
编辑:如果你不使用的MSTest的单元测试,您可能需要手动生成的存取。从本质上讲,你创建一个包装类,它通过等价的公共方法公开被测试类的私有/受保护方法,将被测试类的实例传递给包装,然后使用包装类的反射来调用private/protected方法在被测试的类上。
public class MyClass
{
protected void DoSomething(int num)
{
}
}
public class MyClass_accessor
{
private MyClass privateObj;
public MyClass_accessor(MyClass obj)
{
this.privateObj = obj;
}
public void DoSomething(int num)
{
MethodInfo info = privateObj.GetType()
.GetMethod("DoSomething",
BindingFlags.NonPublic
| BindingFlags.Instance);
info.Invoke(obj,new object[] { num });
}
}
我最近有一个类似的问题,找不到满意的解决方案。所以我创建了自己的帮助函数,它调用OnActionExecuted和OnActionExecuting。看到这里的代码http://mkramar.blogspot.com.au/2012/06/onactionexecuting-and-onactionexecuted.html
我试图做到这一点,但我其实想测试自定义的结果属性,因为它适用于实际控制。在我们的例子中,我们有一个授权属性,在控制器上设置属性,然后控制器使用属性。我们的代码看起来是这样的:
// Create the controller to test
PortalController controller = new PortalController();
var method = typeof(PortalController);
var attribute = method.GetCustomAttributes(typeof(OrganizationContextFilter),true).Cast<OrganizationContextFilter>().SingleOrDefault();
// Set the controller Context with our fake objects on it
controller.ControllerContext = this.GetDefaultControllerMock(controller);
// Execute the Organization Context Filter
var actionDescriptor = new Mock<ActionDescriptor>();
var context = Mock.Get(actionDescriptor.Object);
context.Setup(s => s.ControllerDescriptor).Returns(new Mock<ControllerDescriptor>().Object);
// Use the current controller Context
ActionExecutingContext filterContext = new ActionExecutingContext(controller.ControllerContext, actionDescriptor.Object, new Dictionary<string, object>());
attribute.OnActionExecuting(filterContext);
// We have to use this one, because it has the result of the Attribute execution
PortalController pc = filterContext.Controller as PortalController;
ActionResult result = pc.MethodToTest(); // Call the controller that had OnActionExecuting results
这样做的好处是,我们实际执行我们实际上是在测试控制器上的自定义属性MVC。这既执行自定义属性代码,又在更像“真实世界”的情况下测试控制器。
这是MSTest特有的吗?我正在使用nunit和xunit atm。 – 2009-02-26 18:20:43
我只问,因为我没有看到'添加访问器'的上下文按钮,做一个谷歌搜索带给我一些MS测试特定的东西。 – 2009-02-26 18:21:43
是的,我认为是。我认为它至少需要VS Pro才能在那里。您可以手动创建一个,并使用反射来调用底层专用对象上的适当方法。 – tvanfosson 2009-02-26 19:36:52