Moqを使用してメソッド呼び出しを確認する


142

私はC#での単体テストとMoqの使い方を学ぶのが初めてです。以下は、私がテストしようとしているクラスです。

class MyClass
{
    SomeClass someClass;
    public MyClass(SomeClass someClass)
    {
        this.someClass = someClass;     
    }

    public void MyMethod(string method)
    {
        method = "test"
        someClass.DoSomething(method);
    }   
}

class Someclass
{
    public DoSomething(string method)
    {
        // do something...
    }
}

以下は私のTestClassです:

class MyClassTest
{
    [TestMethod()]
    public void MyMethodTest()
    {
        string action="test";
        Mock<SomeClass> mockSomeClass = new Mock<SomeClass>();
        mockSomeClass.SetUp(a => a.DoSomething(action));
        MyClass myClass = new MyClass(mockSomeClass.Object);
        myClass.MyMethod(action);
        mockSomeClass.Verify(v => v.DoSomething(It.IsAny<string>()));
    }
}

次の例外が発生します。

Expected invocation on the mock at least once, but was never performed
No setups configured.
No invocations performed..

メソッド「MyMethod」が呼び出されているかどうかを確認したいだけです。何か不足していますか?


1
SomeClass定義がない場合はコンパイルされませんが、MyMethod(string)そうではないようです。
プラチナAzure

sorry..Iは..私の質問を編集しました
user591410

1
順調ですが、投稿されたコードにバグがあります。それはコンパイルされません-Someclassでは大文字、DoSomethingでは無効な戻り値。その後、パブリックアクセスが必要になり、DoSomethingを仮想化します。要するに、あなたはおそらくあなたのプロダクションコードにもバグがあります。
TrueWill、2012

御返答いただき有難うございます。私はモックメソッドを設定しながら、引数の間違った設定された...
user591410

「設定されていません。」誤解を招く可能性があります。呼び出されるメソッドの動作を設定する必要はありません。また、テストしているメソッドを呼び出す必要がある場合は、「Verify」メソッドを実行することも忘れないでください(この場合は問題ありません)。
Sielu 2016年

回答:


208

間違ったメソッドをチェックしています。Moqでは、依存関係クラスのメソッドをセットアップ(およびオプションで確認)する必要があります。

あなたはこのようなことをもっとすべきです:

class MyClassTest
{
    [TestMethod]
    public void MyMethodTest()
    {
        string action = "test";
        Mock<SomeClass> mockSomeClass = new Mock<SomeClass>();

        mockSomeClass.Setup(mock => mock.DoSomething());

        MyClass myClass = new MyClass(mockSomeClass.Object);
        myClass.MyMethod(action);

        // Explicitly verify each expectation...
        mockSomeClass.Verify(mock => mock.DoSomething(), Times.Once());

        // ...or verify everything.
        // mockSomeClass.VerifyAll();
    }
}

言い換えると、を呼び出すことを確認していMyClass#MyMethodます。クラスは間違いなくSomeClass#DoSomethingそのプロセスで一度呼び出されます。Times引数は必要ないことに注意してください。私はその価値を実証しただけでした。


申し訳ありませんが、正しい方法で質問を編集しました。おっしゃったように、最初にSetUpを試し、次にVerifyを実行しました。それでも私には同じ例外があります。
user591410

22
期待値を設定して、同じ期待値を明示的に検証することは冗長ではありませんか?思いませんmockSomeClass.VerifyAll();、同じ結果を達成し、よりDRYこと?
ティムロング

13
はい、そうですが、一部の人々は明示的であることを好む。
Platinum Azure

3
少なくともVerifyAll()について言及していただきありがとうございます。一度考えれば明らかです。私は明示的なアプローチをとったかもしれませんが、allを使用するとはるかにクリーンになります。ありがたい両方がリストされています。
JGood 2016

1
Mockと比較しNSubstituteた場合の関連する欠点の1つは、パラメーターも検証しようとして検証が失敗した場合、実行された呼び出しが表示されるだけで、検証式で変数を使用した場合に何が予期されていたのかが表示されないことです。変数のみが表示されます。値ではなく名前なので、デバッグして、その変数がどのような値を持っているかを正確に確認する必要があります。NSubstituteは、両方の値と、それが異なっていた場所を表示します。
グレンガス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.