17

PRISM イベント アグリゲーターを介してイベントをサブスクライブするクラスがあります。

hereに記載されているように、イベント アグリゲーターをモックするのはやや難しいため、実際のイベント アグリゲーターをインスタンス化して、テスト対象のシステムに渡します。

私のテストでは、そのアグリゲーターを介してイベントを公開し、テスト対象のシステムがそれにどのように反応するかを確認します。イベントは本番中に FileSystemWatcher によって発生するため、UIThread をサブスクライブして自動ディスパッチを利用したいので、イベントが発生したら UI を更新できます。

問題は、テスト中に、UIThread をサブスクライブしない限り、テスト中のシステムでイベントが認識されないことです。

TDD.Net 経由で VS2008 内から実行するテストに MSpec を使用しています。テストクラスに追加[RequiresSta]しても役に立たなかった

私のテスト中に ThreadOption を変更することから私を救う解決策はありますか(たとえば、プロパティを介して - なんて醜いハック)???

4

3 に答える 3

22

イベントと Event Aggregator の両方をモックし、moq の Callback を使用すると、それが可能になります。

次に例を示します。

Mock<IEventAggregator> mockEventAggregator;
Mock<MyEvent> mockEvent;

mockEventAggregator.Setup(e => e.GetEvent<MyEvent>()).Returns(mockEvent.Object);

// Get a copy of the callback so we can "Publish" the data
Action<MyEventArgs> callback = null;

mockEvent.Setup(
    p =>
    p.Subscribe(
        It.IsAny<Action<MyEventArgs>>(), 
        It.IsAny<ThreadOption>(), 
        It.IsAny<bool>(), 
        It.IsAny<Predicate<MyEventArgs>>()))
        .Callback<Action<MyEventArgs>, ThreadOption, bool, Predicate<MyEventArgs>>(
        (e, t, b, a) => callback = e);


// Do what you need to do to get it to subscribe

// Callback should now contain the callback to your event handler
// Which will allow you to invoke the callback on the test's thread
// instead of the UI thread
callback.Invoke(new MyEventArgs(someObject));

// Assert
于 2012-03-13T23:30:17.880 に答える
19

EventAggregator ではなく、すべてにモックを使用する必要があると本当に思います。モックするのはまったく難しくありません...リンクされた回答が、EventAggregatorのテスト可能性について多くを証明しているとは思いません。

これがあなたのテストです。私は MSpec を使用しませんが、Moq でのテストは次のとおりです。コードを提供しなかったので、リンク先のコードに基づいています。あなたのシナリオは、リンクされたシナリオよりも少し難しいです。なぜなら、他の OP は、サブスクライブが呼び出されていることを確認する方法を知りたかっただけですが、実際には、サブスクライブで渡されたメソッドを呼び出したいのです...もっと難しいことではありません。とても。

//Arrange!
Mock<IEventAggregator> eventAggregatorMock = new Mock<IEventAggregator>();
Mock<PlantTreeNodeSelectedEvent> eventBeingListenedTo = new Mock<PlantTreeNodeSelectedEvent>();

Action<int> theActionPassed = null;
//When the Subscribe method is called, we are taking the passed in value
//And saving it to the local variable theActionPassed so we can call it.
eventBeingListenedTo.Setup(theEvent => theEvent.Subscribe(It.IsAny<Action<int>>()))
                    .Callback<Action<int>>(action => theActionPassed = action);

eventAggregatorMock.Setup(e => e.GetEvent<PlantTreeNodeSelectedEvent>())
                   .Returns(eventBeingListenedTo.Object);

//Initialize the controller to be tested.
PlantTreeController controllerToTest = new PlantTreeController(eventAggregatorMock.Object);

//Act!
theActionPassed(3);

//Assert!
Assert.IsTrue(controllerToTest.MyValue == 3);
于 2010-03-04T23:29:53.950 に答える