2017-08-25 6 views
1

で、WPF MVVMユニットテストを一致しなかった私は、彼らがしているときにユーザがYesNoCancelメッセージボックスで「はい」ボタンをクリックしたかどうかをテストするために部品番号WPFでユニットテストを書いていますウィンドウを閉じる。私のCloseCommandでは、私は私のViewModelを持っているユーザーは、ウィンドウを閉じているとき、次のメッセージを表示します。以下のセットアップが部品番号

var result = _messageSvc.Show(
    "Do you want to save changes?", 
    "Save Changes", 
    Services.MessageBoxButton.YesNoCancel, 
    Services.MessageBoxIcon.Question, 
    Services.MessageBoxResult.Yes); 

_messageSvcは、メッセージボックスを表示するカスタムメッセージングサービスの内部のプライベートインスタンスです。ここではサービスのためのコードは次のとおりです。

public interface IMessageSvc 
{ 
    void Show(string message); 
    MessageBoxResult Show(string message, string caption, MessageBoxButton buttons, MessageBoxIcon icon, MessageBoxResult defaultResult = 0); 
} 

public class MessageSvc : IMessageSvc 
{ 
    public void Show(string message) 
    { 
     MessageBox.Show(message); 
    } 

    public MessageBoxResult Show(string message, string caption, MessageBoxButton buttons, MessageBoxIcon icon, MessageBoxResult defaultResult) 
    { 
     return (MessageBoxResult)MessageBox.Show(message, caption, (System.Windows.MessageBoxButton)buttons, (System.Windows.MessageBoxImage)icon, (System.Windows.MessageBoxResult)defaultResult); 
    } 
} 

注:MessageBoxButtonMessageBoxIcon、およびMessageBoxResultは、私は.NETが箱から出して提供するものを模倣するために、同じファイルで行われた列挙されています。

[TestMethod] 
public void ShouldAskToSaveOnCloseRespondYesTest() 
{ 
    // Mock and setup initial user data 
    var u= new User 
    { 
     UserId = 1, 
     UserName = "FirstName LastName", 
     FavoriteColor = "Blue" 
    }; 
    mainViewModel.UserInfo= new UserInfoDtoWrapper(u); 

    // assert the data has not changed yet 
    Assert.IsFalse(mainViewModel.UserInfo.IsChanged); 

    // change the user data 
    mainViewModel.UserInfo.UserName= "LastName FirstName"; 

    // assert the data has changed 
    Assert.IsTrue(mainViewModel.UserInfo.IsChanged); 

    // execute window closing 
    mainViewModel.CloseCommand.Execute(new object()); 

    // verify messagebox shows and the 'Yes' button is clicked 
    // this will then save the changes made to the user instance 
    var messageBox = new Mock<IMessageSvc>(); 
    messageBox.Setup(x => x.Show(It.Is<string>(y => y == "Do you want to save changes?"), 
     It.Is<string>(y => y == "Save Changes"), 
     It.Is<MessageBoxButton>(y => y == MessageBoxButton.YesNoCancel), 
     It.Is<MessageBoxIcon>(y => y == MessageBoxIcon.Question), 
     It.Is<MessageBoxResult>(y => y == MessageBoxResult.Yes))) 
     .Returns(MessageBoxResult.Yes); 

    messageBox.Verify(); 
} 

エラーがmessageBox.Verify()オンラインになるが、私は、私はそれを正しくやって見ることができるものから:私は私のユニットテストがある可読性

のためにここでそれらを示していないです。ユーザが「はい」ボタンをクリックした後に何が起こるかをテストするためにメッセージボックスの戻り値を取得する必要があるため、VerifyをLinqクエリで使用したくない代わりに結果を取得する必要があります。

おかげ

+0

"エラーメッセージボックスにはエラーが表示されます。 –

+0

ShouldAskToSaveOnCloseRespondYesTest例外が発生しました:Moq.MockVerificationException:次の設定が一致しませんでした:IMessageSvc x => x.Show(It.Is (y => y == "変更を保存しますか?")、It.Is (y => y == "Save Changes")... –

+0

セットアップと検証の間の残りの部分はどこですか?現在はテストは実行されていません –

答えて

2

これは動作しません。あなたが最初にそのサービスのモックを(IMessageSvc.Showメソッドを呼び出すと想定される)CloseCommandを発射し、だけにして、セットアップ

  1. :あなたは、あなたのテストコードで2つの問題を持っています。

  2. サービスの新しいモックを設定しましたが、使用しません。これらのエラーを修正するには

  • 変更それはアレンジ "正しいような順序 - 「行為」 - 「アサート」ため
  • ビューモデルでは、あなたの嘲笑のサービスを注入ここで、依存性注入

を使用する例である:

class MainViewModel 
{ 
    private readonly IMessageSvc _messageSvc; 

    public MainViewModel(IMessageSvc svc) 
    { 
     this._messageSvc = svc; 
    } 
} 

[TestMethod] 
public void ShouldAskToSaveOnCloseRespondYesTest() 
{ 
    // Arrange 
    var messageBox = new Mock<IMessageSvc>(); 
    messageBox.Setup(x => x.Show(It.Is<string>(y => y == "Do you want to save changes?"), 
     It.Is<string>(y => y == "Save Changes"), 
     It.Is<MessageBoxButton>(y => y == MessageBoxButton.YesNoCancel), 
     It.Is<MessageBoxIcon>(y => y == MessageBoxIcon.Question), 
     It.Is<MessageBoxResult>(y => y == MessageBoxResult.Yes))) 
     .Returns(MessageBoxResult.Yes) 
     .Verifiable(); 

    var mainViewModel = new MainViewModel(messageBox.Object); 

    // Act 
    mainViewModel.CloseCommand.Execute(new object()); 

    // Assert 
    messageBox.Verify(); 
} 
+0

ユニット・テスト・クラスの初期化時にビュー・モデル・コンストラクタにメッセージ・サービス・オブジェクトを追加して、そこから注入されています。しかし、単体テスト方法の中で、自分のコードをどのように見せても、同じエラーが発生しています。 –

+0

@ J-man、いいえ、私が提案したようにコードを整理していません。あなたはあなたのテストメソッドであなたのサービスのための新しいモックを作成しています。まさしくこの模擬サービスは、ビューモデルに提供されなければなりません。私が提案したテストメソッドでビューモデルを作成するか、ビューモデルが作成されたクラス初期化でサービスモックを設定する必要があります。 – dymanoid

+0

あなたは正しい@dymanoidです。ユニットテストクラスのinitializeメソッドで注入されたクラススコープのmessageSvcオブジェクトに既にアクセスしているときに、誤ってメッセージングサービスの新しい疑惑インスタンスを設定していました。ですから、私は 'messageSvc.Setup(...)'を設定していたはずです。var messageBox = new Mock (); messageBox.Setup(...) '。正しいセットアップが見つからないのは不思議ではありません.SAMEオブジェクトをVMに注入する必要があります。誤って新しいオブジェクトを注入しようとしました。ありがとう!!私はあなたの答えを答えとしてマークします。 –

0

現在の模擬メソッドは、のコードをテストした後に設定しています。テストをAAA (Arrange, Act, Assert)パターンに再配置します。

var messageBox = new Mock<IMessageSvc>(); 
messageBox.Setup(x => x.Show(It.Is<string>(y => y == "Do you want to save changes?"), 
    It.Is<string>(y => y == "Save Changes"), 
    It.Is<MessageBoxButton>(y => y == MessageBoxButton.YesNoCancel), 
    It.Is<MessageBoxIcon>(y => y == MessageBoxIcon.Question), 
    It.Is<MessageBoxResult>(y => y == MessageBoxResult.Yes))) 
    .Returns(MessageBoxResult.Yes); 

mainViewModel.CloseCommand.Execute(new object()); 

messageBox.Verify(x => x.Show(It.Is<string>(y => y == "Do you want to save changes?"), 
    It.Is<string>(y => y == "Save Changes"), 
    It.Is<MessageBoxButton>(y => y == MessageBoxButton.YesNoCancel), 
    It.Is<MessageBoxIcon>(y => y == MessageBoxIcon.Question), 
    It.Is<MessageBoxResult>(y => y == MessageBoxResult.Yes))); 
+0

私はこれを前に試しましたが、この状況で返されているエラーは 'Mock上の期待呼び出しですが、' messageBox.Verify(x => x.Show( It.Is It.Is (y => y == "変更を保存")、 It.Is (y => y == "MessageBoxButton.YesNoCancel")は、変更を保存しますか? 、 It.Is (y => y == MessageBoxIcon.Question)、 (y => y == MessageBoxResult.Yes))、Times.Once); ' –

+0

IMessageServiceはViewModelに注入され、Unit Testクラスで初期化されますので、 '_messageSvc.Verify(x => x.Show(It.Is (y => y =="変更を保存しますか? )、 It.Is (y => y == "Save Changes")、 It.Is (y => y == MessageBoxButton.YesNoCancel)、 It.Is (y => y = = MessageBoxResult.Yes))、それは動作しますが、戻り値を取得するためにメッセージボックスをセットアップする必要があります(MessageBoxResult.Yes == MessageBoxResult.Yes) –

関連する問題