2009-02-26 73 views

回答

15

您需要添加和使用一個專用訪問器。右鍵單擊您的控制器類,然後從菜單中選擇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 }); 
     } 
    } 
+0

這是MSTest特有的嗎?我正在使用nunit和xunit atm。 – 2009-02-26 18:20:43

+0

我只問,因爲我沒有看到'添加訪問器'的上下文按鈕,做一個谷歌搜索帶給我一些MS測試特定的東西。 – 2009-02-26 18:21:43

+0

是的,我認爲是。我認爲它至少需要VS Pro才能在那裏。您可以手動創建一個,並使用反射來調用底層專用對象上的適當方法。 – tvanfosson 2009-02-26 19:36:52

0

我試圖做到這一點,但我其實想測試自定義的結果屬性,因爲它適用於實際控制。在我們的例子中,我們有一個授權屬性,在控制器上設置屬性,然後控制器使用屬性。我們的代碼看起來是這樣的:

// 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。這既執行自定義屬性代碼,又在更像「真實世界」的情況下測試控制器。

相關問題