134

次のインターフェースがあるとします。

public interface IFoo
{
    bool Foo(string a, bool b = false);
}

Moqを使用してモックしようとしています:

var mock = new Mock<IFoo>();
mock.Setup(mock => mock.Foo(It.IsAny<string>())).Returns(false);

コンパイル時に次のエラーが発生します。

式ツリーには、オプションの引数を使用する呼び出しまたは呼び出しを含めることはできません

上記の問題は、Moq の問題リストの拡張機能として提起されていることがわかりました。これは、4.5 リリースに割り当てられているようです (いつでも)。

私の質問は、上記がすぐに修正されないことを考えると、どうすればよいですか? オプションのパラメーターをモックするたびにデフォルト値を明示的に設定するか (これは、最初にパラメーターを指定するという点を無効にします)、ブール値を使用せずにオーバーロードを作成するか (私が行ったように) するためのオプションのみです。 C# 4) より前ですか?

または、この問題を克服するためのより賢い方法に出くわした人はいますか?

4

4 に答える 4

98

bool現時点での唯一の選択肢は、 のセットアップにパラメータを明示的に含めることだと思いますFoo

デフォルト値を指定する目的に反するとは思いません。デフォルト値はコードを呼び出すのに便利ですが、テストでは明示する必要があると思います。パラメータの指定を省略できるとしboolます。将来、誰かが のデフォルト値をbに変更するとどうなりtrueますか? これはテストの失敗につながります (当然のことですが) が、 という隠れた仮定があるため、修正がより困難になりbますfalse。パラメータを明示的に指定することには、bool別の利点があります。テストの可読性が向上します。それらを調べているFoo人は、2 つのパラメーターを受け取る関数が 1 つあることにすぐに気付くでしょう。それは少なくとも私の2セントです:)

モックするたびに指定する場合は、コードを複製しないでください。関数内でモックを作成および/または初期化して、変更点が1つだけになるようにします。Foo本当にしたい場合は、のパラメータをこの初期化関数に複製することで、ここで Moq の明らかな欠点を克服できます。

public void InitFooFuncOnFooMock(Mock<IFoo> fooMock, string a, bool b = false)
{
    if(!b)
    {
        fooMock.Setup(mock => mock.Foo(a, b)).Returns(false);
    }
    else
    {
        ...
    }
}
于 2012-10-19T16:41:35.527 に答える