2009-09-15 16 views
21

MVPパターンusing this exampleを実装しようとしているasp.net(クラシック)アプリケーションを開発しています。私のプレゼンターテストユニットにしようと、次のパターンを使用して、擬似コードは、そのためにどのように私はプレゼンターを初期化し、ロードイベントのために登録する、すなわち何を期待されてやっていることを確認しますのでMoqを使用したイベント登録の確認

//base view interface 
public interface IView 
{ 
    event EventHandler Init; 

    event EventHandler Load; 

    bool IsPostBack { get; } 

    void DataBind(); 

    bool IsValid { get;} 
} 

//presenter psuedo code 
public class SomePresenter 
{ 
    public SomePresenter(ISomeDomainService service, IView someView) 
    { 
      ... 
      //HOW DO WE TEST/VERIFY THAT THIS REGISTRATION OCCURS? 
      someView.Init += OnInit; 
      someView.Load += OnLoad; 
    } 
} 
... 
//consuming code that exercises the above code, that needs to be tested 
var presenter = new SomePresenter(someDomainService, someView); 

のように見えますか?これは、簡単にどのように我々はMOQを使ってこれを行うことができます... ... Rhinoのモックを使用してPhil Haack's example

[Test] 
public void VerifyAttachesToViewEvents() 
{ 
    viewMock.Load += null; 
    LastCall.IgnoreArguments(); 
    viewMock.PostSaved += null; 
    LastCall.IgnoreArguments(); 
    mocks.ReplayAll(); 
    new PostEditController(viewMock, 
     this.dataServiceMock); 
    mocks.VerifyAll(); 
} 

に行われますが?

+1

1 - 私の頭を打ちます同じ壁に対して – Gishu

答えて

14

この機能はmoqではnot currently availableであると思われますが、将来のバージョンで表示される可能性があります(4.0.812.4ベータ版の外観ですが、そこにはないようです)。

「なぜSomePresenterは、ViewのLoadInitイベントに登録する必要がありますか?」という質問をする価値があります。恐らく、SomePresenterクラスがこれらのイベントに応答する必要があるからです。したがって、のRaiseメソッドを使用して、LoadイベントとInitイベントを発生させ、それに応じてSomePresenterが正しいことをしたと主張してください。

+1

私はそれについて考えました。基本的に、このコードをテストするには2つの部分があります。 1.インタラクションテスト...イベント登録を確認します 2.状態ベースのテスト...これは、プレゼンタのイベントハンドラが期待どおりに動作することを確認します。 クリーンユニットテストは、それぞれのケースを個別にテストすることです。 (1)の1つの解決策は、IViewインタフェースに2つのメソッドを追加することです。 public interface IView { ... public void RegisterForInit(EventHandler callback); ... } 及び公共SomePresenter(...){ ... someView.RegisterFoInit(のOnInit)にプレゼンタコンストラクタを修正します。 } –

+0

となり、イベントサブスクリプションがある場合は、MOQのStrict Mocksを使用できません。 – Gishu

+0

この懸念に関するGitHubの問題(https://github.com/Moq/moq4/issues/49)へのリンクが更新されました。 – KevM

0

私はこの質問にいくつかの時間を過ごし、私は私のプロジェクトで使用しているソリューションは、次のとおりです。

ユニットテスト:

// Arrange 
TestedObject.Setup(x => x.OnEvent1()); 
TestedObject.Setup(x => x.OnEvent2()); 

// Act 
TestedObject.Object.SubscribeEvents(); 
TestedObject.Raise(x => x.Event1 += null); 
TestedObject.Raise(x => x.Event2 += null); 

// Assert 
TestedObject.Verify(x => x.OnEvent1(), Times.Once()); 
TestedObject.Verify(x => x.OnEvent2(), Times.Once()); 

テスト済みの方法:

this.Event1 += OnEvent1; 
this.Event2 += OnEvent2; 

まずは、私に電話をした後、イベントを割り当てるメソッドをモックする必要がありますあなたがテストしたいthodを作成し、最後にすべての購読済みのイベントを発生させます。イベントが実際に購読されている場合は、割り当てられたメソッドが呼び出された場合はMoqでチェックできます。

GLHF!

+4

これは混乱しています。 OnEvent1()メソッドはテスト中のオブジェクトにあり、Raise()はモックされたオブジェクトに対して呼び出す必要があります。表示されているすべてのクラスで実際の作業コードを投稿できますか? –

0

私はそれが#Dilipには遅すぎる可能性があることを知っていますが、この回答は同じことをやろうとしている人にとって有益です。ここ は、テストクラスはFakeView

public delegate void SubscriptionHandler<T>(string name, T handler); 

public class SomePresenterTest 
{ 
    [Test] 
    public void Subscription_Test() 
    { 
     var someServiceMock = new Mock<ISomeDomainService>(); 
     var viewMock = new Mock<IView>(); 
     //Setup your viewMock here 

     var someView = new FakeView(viewMock.Object); 
     EventHandler initHandler = null;    
     someView.Subscription += (n, h) => { if ((nameof(someView.Init)).Equals(n)) initHandler=h; }; 

     Assert.IsNull(initHandler); 

     var presenter = new SomePresenter(someServiceMock.Object, someView); 

     Assert.IsNotNull(initHandler); 
     Assert.AreEqual("OnInit", initHandler.Method?.Name); 
    } 
} 

です(イベントに注意を払う:初期化/ロード{追加し、削除}):次のように実装されデコレータです

public class FakeView : IView 
{ 
    public event SubscriptionHandler<EventHandler> Subscription; 
    public event SubscriptionHandler<EventHandler> Unsubscription; 
    private IView _view; 
    public FakeView(IView view) 
    { 
     Assert.IsNotNull(view); 
     _view = view; 
    } 

    public bool IsPostBack => _view.IsPostBack; 
    public bool IsValid => _view.IsValid; 

    public event EventHandler Init 
    { 
     add 
     { 
      Subscription?.Invoke(nameof(Init), value); 
      _view.Init += value; 
     } 

     remove 
     { 
      Unsubscription?.Invoke(nameof(Init), value); 
      _view.Init -= value; 
     } 
    } 
    public event EventHandler Load 
    { 

     add 
     { 
      Subscription?.Invoke(nameof(Load), value); 
      _view.Init += value; 
     } 

     remove 
     { 
      Unsubscription?.Invoke(nameof(Load), value); 
      _view.Init -= value; 
     } 
    } 

    public void DataBind() 
    { 
     _view.DataBind(); 
    } 
} 
関連する問題