Moqを使用してメソッドが呼び出されたかどうかを判別する


159

より高いレベルのメソッドを呼び出すと、メソッド呼び出しが発生することをテストできることは理解しています。つまり、

public abstract class SomeClass()
{    
    public void SomeMehod()
    {
        SomeOtherMethod();
    }

    internal abstract void SomeOtherMethod();
}

私が呼び出すSomeMethod()場合、それSomeOtherMethod()が呼び出されることを期待しているかをテストしたいと思います。

この種のテストはモックフレームワークで利用できると思いますか?

回答:


186

以下の例のように、Verifyを使用して、モックしたもののメソッドが呼び出されたかどうかを確認できます。

static void Main(string[] args)
{
        Mock<ITest> mock = new Mock<ITest>();

        ClassBeingTested testedClass = new ClassBeingTested();
        testedClass.WorkMethod(mock.Object);

        mock.Verify(m => m.MethodToCheckIfCalled());
}

class ClassBeingTested
{
    public void WorkMethod(ITest test)
    {
        //test.MethodToCheckIfCalled();
    }
}

public interface ITest
{
    void MethodToCheckIfCalled();
}

行がコメント化されたままの場合、Verifyを呼び出すとMockExceptionがスローされます。コメントされていない場合は合格です。


7
これが正解です。ただし、何かを理解する必要があります。抽象的または仮想的でないメソッド/プロパティをモックすることはできません(明らかに、すべてのインターフェースメソッドとプロパティはモックできます)。

25
-1:このコードでは、.Expect(...)。Verifiable()は冗長です。AAAを使用して、あなたが持っている検証がちょうど良いです。.Verifiableは.Verify()で使用するためのものです。引数なしのバージョン。stackoverflow.com/questions/980554/…を
Ruben Bartelink 2009年

@ I--はい、可能です
レゲエギター

6

いいえ、模擬テストでは、インジェクションなどの特定のテスト可能な設計パターンを使用していることを前提としています。あなたのケースでは、テストされるだろうSomeClass.SomeMethodSomeOtherMethodインタフェースされる必要がある別のエンティティに実装する必要があります。

あなたのSomeclassコンストラクタは次のようになりますNew(ISomeOtherClass)。次に、をモックしてISomeOtherClassSomeOtherMethod呼び出される期待値を設定し、期待値を確認します。


0

@Paul の回答が推奨される方法であることには同意しますが、自分で提供する別の方法を1つ追加するだけですmoq

以来でSomeClassあるabstractことは確かmockableですが、public void SomeMehod()ではありません。ポイントは、そのメソッドをモックして何らかの方法で呼び出す方法を見つけ、それを使用しCallBaseてへの呼び出しを伝達することSomeOtherMethod()です。ハックのように聞こえるかもしれませんが、本質的には単純です。提案されたリファクタリングが不可能な場合に使用できます。

// This class is used only for test and purpose is make SomeMethod mockable
public abstract class DummyClass : SomeClass
{
    public virtual void DummyMethod() => base.SomeMethod();
}

次にDummyMethod()CallBaseフラグを設定することにより、コールを伝播するように設定できます。

//Arrange
var mock = new Mock<DummyClass>();
mock.Setup(m => m.DummyMethod()).CallBase();

//Act
mock.Object.SomeMethod();

//Assert
mock.Verify(m => m.SomeOtherMethod(), Times.Once);

それはより複雑で定型のDummyClassを必要とするため、反対票を投じました
reggaeguitar

時々リファクタリングができず、
現状の
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.