2011-12-19 11 views
8

メッセージボックスを論理から切り離すための最良の方法を見つけるために、私は適切にユニットテストをすることができます。今私はちょうど私がメッセージボックスのために後でスタブすることができる別個のヘルパークラス(C#)を作ればそれが十分であるかどうか疑問に思っていました。例えば:メッセージボックスとユニットテスト

static class messageBoxHelper 
{ 
    public static void msgBoxAlg(string message, string title, MessageBoxButtons buttons, MessageBoxIcon icons, bool show) 
    { 
     if (show) 
     { 
      MessageBox.Show(message, title, buttons, icons); 
     } 
} 

はその後、毎回私は私がだけではなく、messagebox.show(...)のmessageboxHelper/msgBoxAlg(...)を使用したいメッセージボックスを使用する必要があるだろう。ブール・ショーを使ってテスト中にそれを有効または無効にすることができました。

これが「正しい方法」であるかどうかは不思議です。これを正しく行うためのより簡単な方法がありますか?私はメッセージボックスを捨てることはできません。ユーザーに "重要な"情報を中継します( "このウィンドウを閉じますか?" YES/NOなど)。また、私は適切なソフトウェアエンジニアリングを使用していないこともあります。私はメッセージボックスを自分のビジネスロジックから切り離すべきですか?

答えて

29

はい、正しいです。しかし、その代わりに静的クラスの、あなたはIDialogServiceを実装する必要がありますとダイアログが表示されるはずのクラスに注入:あなたはIDialogServiceの代わりに、実際の1のモックオブジェクトを注入する必要がありSomeClassをテスト中

public interface IDialogService 
{ 
    void ShowMessageBox(...); 

    ... 
} 

public class SomeClass 
{ 
    private IDialogService dialogService; 

    public SomeClass(IDialogService dialogService) 
    { 
     this.dialogService = dialogService; 
    } 

    public void SomeLogic() 
    { 
     ... 
     if (ok) 
     { 
      this.dialogService.ShowMessageBox("SUCCESS", ...); 
     } 
     else 
     { 
      this.dialogService.ShowMessageBox("SHIT HAPPENS...", ...); 
     } 
    } 
} 

さらに多くのUIロジックをテストする必要がある場合は、MVVMパターンを使用することを検討してください。

+0

ありがとう、非常に明確な説明! –

+0

私は抽象として "IDialogService"という言葉が大好きです! – Samuel

2

Inversion of Control(IoC)を調べると、基本的なプリンシパルは、アクションを実行するものがインターフェイスとして渡され、次にIoCコンテナを使用してインターフェイスがアプリケーションの特定の実装にバインドされるということです。あなたのケースでこれを簡単に達成するには、メッセージボックスをインターフェイスとして使用し、ユニットテストでメッセージボックスを表示しないメッセージボックスサービスの模擬(偽)バージョンを

http://martinfowler.com/articles/injection.html IoCの詳細は、私の好きなコンテナはNinject(http://ninject.org)

1

理想的には、単体テストでテストしたコードをロジックではなくUIにすることが理想的です。したがって、論理はあなたのテスト本当にメッセージボックスを表示してはいけません。 UIをテストしたい場合は、Coded UI Testsを提案します。

あなたの質問で判断すると、あなたのコードは本当にMessageBoxを使用するべきではないと思います。代わりに、代わりにコールバックを使用するか、任意のActionを使用するか、Luke McGregorとSergey Vに記載されている手法を使用することを検討してください。

1

「ユニットテスト」は、正確な意味でアトミックな動作のテストです。これはコードに対して行うことができる唯一のコード駆動テストではありません。特に言及している「Yes/No」ダイアログを使用してより長いシナリオをテストする場合は、大規模なコード駆動テストが単体テストより効果的であることがよくあります。でメッセージボックスをラップすることによって

public interface IDialogService 
{ 
    Task<bool> ShowYesNoMessageBox(...); 
    ... 
} 

は、しかしそれらを簡単に書くことができるようにするために、セルギで述べたような特別なサービスを作成するには、だけでなく、非同期の呼び出しを行うだけでなく、良いでしょう非同期のサービスコールとそれらを嘲笑、長いシナリオでは、実際に起こる前に( "Act"ではなく "Arrange"を行う)ユーザアクションを予測することで "Arrange-Act-Assert"パターンと矛盾し始めます。特にBDD/SpecFlowを使用してテストが行​​われている場合は、テストの問題。これらの呼び出しを非同期にすることで、このような問題を回避できます。メッセージボックスを使用した大規模テストの詳細とサンプルについては、 blog articleを参照してください。

関連する問題