我重寫了我的控制器的OnActionExecuting方法,根據執行的filterContext設置一些內部狀態。我如何測試這個?該方法本身是受保護的,所以我認爲我必須在調用堆棧中更高。如何測試我的asp.net-mvc控制器的OnActionExecuting方法?
我需要測試什麼代碼?
我使用MVC RC 1
編輯:我也使用NUnit。
謝謝
我重寫了我的控制器的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