1

ここで何が起こっているのか少し混乱しています。Model-View-PresenterパターンPuzzle.zipをテストする方法を示すAtomicObjectのパズルの例を見ています。

ビューにはプライベートイベントがあります。ビューには、イベントにデリゲートを追加するSubscribe(delegate)関数もあります。プレゼンターはIViewとIModelで渡されます。構築中に、ビューをサブスクライブし、モデル上の関数に接続します。

プレゼンターの単体テストでは、ViewクラスはNMockを使用してモックされます。したがって、これは単なるダムクラスであり、Subscribe()関数は実際には何もしません。もちろん、プレゼンターをテストするには、ビューとモデルをモックアップしてから、ビューでイベントをトリガーし、モデル関数が呼び出されたことを確認する必要があります。サンプルコードは問題なく動作しますが、どのように動作するのかわかりません!!

いくつかの抜粋:

    private DynamicMock modelMock;
    private IPuzzleModel model;
    private DynamicMock viewMock;
    private IPuzzleView view;
    private SavedTypeOf moveRequestConstraint;

    [SetUp]
    public void SetUp()
    {
        modelMock = new DynamicMock(typeof(IPuzzleModel));
        modelMock.Strict = true;
        model = modelMock.MockInstance as IPuzzleModel;

        // Setup the view
        viewMock = new DynamicMock(typeof(IPuzzleView));
        viewMock.Strict = true;
        view = viewMock.MockInstance as IPuzzleView;

        moveRequestConstraint = new SavedTypeOf(typeof(PointDelegate));
        viewMock.Expect("SubscribeMoveRequest", moveRequestConstraint);

        // create the presenter
        new PuzzlePresenter(model, view);
    }

    [Test]
    public void test_MoveRequest_fromView()
    {
        Point point = new Point(1, 2);
        modelMock.Expect("MoveRequest", point);
        PointDelegate trigger = moveRequestConstraint.GetInstance as PointDelegate;
        trigger(point);
    }

どういうわけか、「trigger(point)」呼び出しは実際にビューに接続されており、ビュー内のプライベートイベントをトリガーしています。これがどのように機能しているかわかりません-ビューインスタンスに接続されている場所がわかりません。私は何が欠けていますか?

更新: NMock 2を使用しようとしています。moveRequestConstraint変数は、TestSetup関数のSubscribeMoveRequest()に渡される値を受け取っているようです。ただし、これはNMock 1構文であり、NMock2はその構文をサポートしていないようです。NMock 2でどのようにそれを行いますか?

4

2 に答える 2

1

テストでドメイン コードを実行していますか? プレゼンターのコンストラクターが例外をスローしないこと以外は、おそらく何もテストしていません。

ちなみに、RhinoMocksを使用することを強くお勧めします。次のようになります。

private IPuzzleModel model;
private IPuzzleView view;
private PointDelegate pointDelegate;
private Point point;

[SetUp]
public void SetUp()
{
    model = MockRepository.CreateMock<IPuzzleModel>();
    view = MockRepository.CreateMock<IPuzzleView>();

    // get the delegate passed to the mock when it is called
    // This is one of the more complex things you do with mocks.
    view.Stub(x => x.Subscribe(Arg<PontDelegate>().Is.Anything)
      .WhenCalled(call => pointDelegate = (PointDelegate)call.Arguments[0];);

    point = new Point(1, 2);
}

[Test]
public void test_MoveRequest_fromView()
{
    PuzzlePresenter presenter = new PuzzlePresenter(model, view);

    // make sure the Delegate method was called and the delegate
    // is available
    Assert.IsNotNull(pointDelegate);

    // fire the delegate.
    pointDelegate(point);

    // check if the model was called.
    model.AssertWasCalled(x => x.MoveRequest(point));
}
于 2009-04-15T14:53:02.517 に答える
0

Presenter First の例を NMock2 で動作させようとして、同じ問題に遭遇しました。

少し掘り下げた後、SourceForge の NMock2 フォーラムで投稿を見つけました。

[Test]
public void test_MoveRequest_fromView()
{
    Mockery mockery = new Mockery();
    IPuzzleView view = mockery.NewMock<IPuzzleView>();
    IPuzzleModel model = mockery.NewMock<IPuzzleModel>();

    CollectAction collect = new CollectAction(0);
    Expect.Once.On(view).Method("SubscribeMoveRequest").Will(collect);
    Expect.Once.On(model).Method("MoveRequest");

    new PuzzlePresenter(model, view);
    Point point = new Point(1, 2);
    PointDelegate del = collect.Parameter as PointDelegate;
    del(point);
    mockery.VerifyAllExpectationsHaveBeenMet();
}

上記のコードを試してみてください - まだ試していませんが、動作するはずです。それは NMock2 の残りの部分のようによく読めませんが、NMock の元のテスト コードもそうではありませんでした。

アップデート:

また、最新の NMock2 (2.0.3411.37113) も CollectAction のジェネリック バージョンをサポートしているようです。

PointDelegate savedPointDelegate = null;
CollectAction<PointDelegate> collect = new CollectAction<PointDelegate>(0,
    delegate(PointDelegate del) { savedPointDelegate = del; });
...
savedPointDelegate(point);

以下は、読みやすさを改善するための私の試みですが、それほど改善されていません。

Expect.Once.On(view).Method("SubscribeMoveRequest").Will(
    Collect.Argument<PointDelegate>(0, delegate(PointDelegate del) { savedPointDelegate = del; }));

public class Collect
{
    public static CollectAction<T> Argument<T>(int index, CollectAction<T>.Collect collectDelegate)
    {
        CollectAction<T> collect = new CollectAction<T>(index, collectDelegate);
        return collect;
    }
}
于 2009-10-06T13:35:42.717 に答える