2011-12-07 17 views
0

基本的な問題はプレゼンターのテスト方法です。Model View Presenterテストの解決策... DTOまたはDomainオブジェクト、またはその両方を使用しますか?

テイク: ドメインオブジェクト(最終的にDBに保持されます) ベース属性されているID(​​DB ID、INT/GUID /何でも)とTransientID(保存、GUIDまでローカルID)

domainObjectの

 
 
namespace domain { 
    public class DomainObject {  
    private int _id;  
    private Guid transientId;  
    public DomainObject() 
    {  
    _transient_Id = Guid.NewGuid();  
    } 
    } 
} 
 

PresenterTest:

 

var repository = Mock.StrictMock(); 
var view = Mock.StrictMock(); 

view.Save += null; 
var saveEvent = LastCall.Ignore().GetEventRaiser(); 

var domainObject = new DomainObject() {Id = 0, Attribute = "Blah"}; 

Mock.ExpectCall(Repository.Save(domainObject)).Returns(True); 
Mock.ReplayAll(); 

var sut = new Presenter(repository, view); 
Save_Event.raise(view, EventArgs.Empty); 

Mock.Verify() 
 

ので、ここでの問題は、ドメインオブジェクトIDはIDとFで計算されていることですそれはtransientIDで計算されているので、transientIDが何であるかを知る方法がないので、モックリポジトリでの等価性のチェックができません。

1)LastCall.Ignoreとメソッドが呼ばれましたことをjsutテストで自分自身をコンテンツが、コールの内容をテストしていない:

回避策は今のところです。

2)DTOをテストしてサービスに保存します。サービスは、ドメインへのマッピングを処理する以上のものです。

3)カスタムロジックを使用して成功を判断する偽のテストリポジトリを作成します。

- 1はロジックの大部分をテストしません。 --2は、良い目的ではない、たくさんの余分なコードです.3潜在的に脆弱であるようです。今私は、DTOのと、それは階層間の最大の分離を与えるが、おそらく75%不要であることを理論的にサービスに傾いてる

は...

答えて

1

transientIDがどのようになるかわからないので、モックリポジトリの平等性をチェックできません。

実際、ここには機会があると思います。

Guid.NewGuid()を呼び出す代わりに、GUIDを生成する独自のGuidFactoryクラスを作成できます。デフォルトでは、内部でGuid.NewGuid()を使用しますが、テストのためにその制御を取ることができます。あなたのコンストラクタで

public static class GuidFactory 
{ 
    static Func<Guid> _strategy =() => Guid.NewGuid(); 

    public static Guid Build() 
    { 
     return _strategy(); 
    } 

    public static void SetStrategy(Func<Guid> strategy) 
    { 
     _strategy = strategy; 
    } 
} 

、あなたはGuidFactory.Build()Guid.NewGuid()を交換してください。

テストセットアップでは、必要に応じて戦略を上書きします。テスト内の別の場所で使用できる既知のGuidを返すか、デフォルトの結果をフィールドに出力するだけです。例えば

public class PseudoTest 
{ 
    IList<Guid> GeneratedGuids = new List<Guid>(); 

    public void SetUpTest() 
    { 
     GuidFactory.SetStrategy(() => 
     { 
      var result = Guid.NewGuid(); 
      GeneratedGuids.Add(result); 
      return result; 
     }); 
    } 

    public void Test() 
    { 
     systemUnderTest.DoSomething(); 
     Assert.AreEqual(GeneratedGuids.Last(), someOtherGuid); 
    } 
} 
+0

それは間違いなく一見の価値がある、ありがとう。 – Gary

1

WPFは、私はあなたが本当にないことを認識し支援してきましたコントローラ/プレゼンタ/ VM上にあれば、多くのテストを行う必要があります。実際には、使用しているモデルやサービスにすべてのテストを集中させる必要があります。すべてのビジネスロジックが存在する必要があり、ビューモデルまたはプレゼンターまたはコントローラーはできるだけ軽くなければならず、モデルとビューの間でやりとりする役割があります。

ボタンコマンドがプレゼンターに表示されたときにサービスを呼び出すかどうかをテストする点は何ですか?または、イベントが適切に配線されているかどうかをテストしますか?

私は間違っていませんが、私はまだビューモデルやコントローラのための非常に小さなテストフィクスチャを持っていますが、テストの焦点はモデル上になければなりません、統合テストは、ビューと発表者。

スキニーコントローラ/ VM /プレゼンター。 脂肪モデル。

これは私が同じ問題をビューモデルをテストしようとしたときに発生したので、私は非常に多くの時間を無駄にしてテストする方法を理解しようとしました。これらのテストを行うには時間をかけすぎず、モデルやサービスに集中してください。

+0

は、合意されたが、このプロジェクトはおよそ完全にプレゼンテーション層をテストしている... IEはMVPパターンに精通し、完全にテスト可能なプレゼンテーション層を構築します。本当にこの答えはLastCall.Ignore、IEと同じになります。イベントが有線であることを確認していますが、発表者のロジックが正しく動作しているかどうかは気にしません。だから、あなたは正しい...どんな現実世界の状況でも:) – Gary

関連する問題