2009-02-26 8 views
10

コントローラのOnActionExecutingメソッドをオーバーライドして、実行中のfilterContextに基づいて内部状態を設定しました。これをどうすればテストできますか?メソッド自体は保護されているので、コールスタックで上位に移動する必要があると仮定します。私のasp.net-mvcコントローラのOnActionExecutingメソッドをユニットテストするにはどうすればいいですか?

これをテストするにはどのようなコードが必要ですか?

私は、MVC RC 1.

Editを使用しています:私はまた、NUnitのを使用しています。

ありがとうございました

答えて

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); 

} 

はEDIT:あなたのユニットテストのためのMSTestをを使用していない場合、あなたは手でアクセサを生成する必要があります。ここに私自身のコードからサンプルテストです。基本的には、テスト対象のクラスのprivate/protectedメソッドを同等のパブリックメソッドで公開し、テスト対象のクラスのインスタンスをラッパーに渡し、ラッパークラスからのリフレクションを使用して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を使用しています。 –

+0

「アクセサーを追加」コンテキストボタンが表示されず、google検索を実行するとmsテストの特定のものが表示されるので、私は尋ねるだけです。 –

+0

はい、そうです。私はそれがそこにいるために少なくともVS Proが必要だと思います。あなたは手動で作成することもできますし、リフレクションを使って基底のプライベートオブジェクトに対して適切なメソッドを呼び出すこともできます。 – tvanfosson

4

私は最近、同様の問題があり、満足のいく解決策を見つけることができませんでした。だから私はOnActionExecutedとOnActionExecutingを呼び出す独自のヘルパー関数を作成しました。 http://mkramar.blogspot.com.au/2012/06/onactionexecuting-and-onactionexecuted.htmlにここ

+0

受け入れられた回答に*コードと説明*がどのように含まれていて、自己宣伝のリンクがないことに注目してください。これが受け入れられる答えのパターンです。 –

+0

私は他を動かすことはありませんでした。しかし、あなたのコードwork.Maybe私はあなたの答えを編集し、コードを追加する必要があります。私はあなたのコードをhttp://stackoverflow.com/a/10316899/648076と組み合わせました。今テストは本当にいいね。 –

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属性を実行することです:私たちのコードは次のようになります。これは、両方ともカスタム属性コードを実行し、コントローラを「現実の世界」のような状況でテストします。

+0

事実の2年後のちょっとした質問 - 派生した属性を通じてコン​​トローラのプロパティを設定するにはどうすればよいですか? – VisualBean

関連する問題