2017-09-25 11 views
0

xUnitのテストでは、リファレンスクラスとテスト済みクラスの間でメソッド呼び出し(シーケンスと値)を比較したいと思います。例えばMoqメソッドの呼び出し順序の比較

public interface ITarget 
{ 
    void A(string val); 
    void B(int val); 
} 

public class RefClass 
{ 
    private readonly ITarget m_target; 
    public RefClass(ITarget target) { this.m_target = target; } 
    public void Work() 
    { 
     this.m_target.A("A"); 
     this.m_target.A("B"); 
     this.m_target.B(0); 
     this.m_target.B(1); 
    } 
} 

public class TestClass 
{ 
    private readonly ITarget m_target; 
    public TestClass(ITarget target) { this.m_target = target; } 
    public void Work() 
    { 
     this.m_target.A("B"); 
     this.m_target.B(1); 
     this.m_target.B(0); 
     this.m_target.A("A"); 
    } 
} 

public class WorkTest 
{ 
    [Fact] 
    public void Work_is_done_in_sequence() 
    { 
     var refTarget = new Mock<ITarget>(); 
     var refClass = new RefClass(refTarget.Object); 
     refClass.Work(); 

     var testTarget = new Mock<ITarget>(); 
     var testClass = new TestClass(testTarget.Object); 
     testClass.Work(); 

     //TODO : compare refTarget and testTarget method call sequence 
    } 
} 

私がテストしたクラスは、ターゲット・インタフェースの参照クラスがないとまったく同じ方法を使用することをどのように比較することができますか?ありがとう。

+0

モックと同じ期待される動作を設定し、それらを検証し、テスト中のメソッドを実行することによって。あなたはモックがどのように使用されているかを示していないので、それをどうやって行うのかあなたに教えることはあまりありません。あなたがしようとしていることを適切に表すために使用できる[mcve]を提供してください。 – Nkosi

+0

あなたは1つのモックをセットアップし、それをターゲットクラスで再利用することもできます。同じ期待動作が2回実行されていることを確認できます。 – Nkosi

答えて

0

だけ事前に定義された値を使用して呼び出しのシーケンスを検証したい場合は、MockSequenceを使用することができます。 注: - 厳密なモックを使用する必要があります。テストは、sut.Do()で失敗しないアサーションの必要になります。

public void TEST() 
{ 
    //arrange 
    var mock = new Mock<ITarget>(MockBehavior.Strict); 
    var seq = new MockSequence(); 
    mock.InSequence(seq).Setup(m => m.A("A1")); 
    mock.InSequence(seq).Setup(m => m.A("A2")); 
    mock.InSequence(seq).Setup(m => m.B("B1")); 
    mock.InSequence(seq).Setup(m => m.B("B2")); 

    var sut = new Sut(mock.Object); 

    //act 
    sut.Do(); 
} 

あなたはそのルートを行くにしたくない場合は、コールバックとセットアップあなたのモックをすることができ、いくつかのリストにパラメータを追加します。

[Test] 
public void TEST() 
{ 
    //arrange 
    var mock = new Mock<ITarget>(); 
    var calls = new List<Tuple<string, string>>(); 
    mock.Setup(m => m.A(It.IsAny<string>())) 
     .Callback<string>(s => calls.Add(new Tuple<string, string>("A", s))); 
    mock.Setup(m => m.B(It.IsAny<string>())) 
     .Callback<string>(s => calls.Add(new Tuple<string, string>("B", s))); 

    var sut = new Sut(mock.Object); 

    //act 
    sut.Do(); 

    //assert 
    //inspect calls 
} 

PS 2つの別々のテストで2つのクラスをテストします。

+0

最後に、StringBuilderを使用して2番目のソリューションのようにしました。 – Dede

0

テストされたクラスがターゲットインターフェイス を参照クラスとまったく同じ方法で使用することを比較するにはどうすればよいですか?

mockの期待される同じ動作を設定し、テスト中のメソッドを実行した後で検証します。

モックを1つセットアップしてターゲットクラスに再利用することもできます。同じ期待動作が2回実行されていることを確認できます。

[Fact] 
public void Work_is_done_in_sequence() { 
    //Arrange 
    var mock = new Mock<ITarget>(); 
    var refClass = new RefClass(mock.Object); 
    var testClass = new TestClass(mock.Object); 

    //Act 
    refClass.Work(); 
    testClass.Work(); 

    //Assert 
    var expected_A_Val = "some_value"; 
    mock.Verify(_ => _.A(expected_A_Val), Times.Exactly(2)); 

    var expected_B_Val = 3; 
    mock.Verify(_ => _.B(expected_B_Val), Times.Exactly(2));   
} 
+0

ITargetメソッドをいくつか呼び出す必要がある場合は、1つずつ記述する必要があるので、これはうれしいことです。実際の実装ではITargetクラスに対して100回の呼び出しが行われるため、サンプルが大幅に削減されます。そのため、テストされたクラスを参照と比較することが可能かどうかを尋ねています。 – Dede

関連する問題