次のインターフェイスがあるとします:
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の問題のリストで enhancement として発生した上記の問題を発見し、4.5リリースに割り当てられているようです(それがいつでも)。
私の質問は次のとおりです。上記がすぐに修正されない場合、どうすればよいですか?私のオプションは、オプションパラメータのデフォルト値をモックするたびに明示的に設定するか(最初に指定するポイントを無効にする)、またはブールなしでオーバーロードを作成する(私がしたことのように) C#4)の前に?
それとも、誰かがこの問題を克服するより賢い方法に出くわしましたか?
現時点での唯一の選択は、bool
のセットアップにFoo
パラメーターを明示的に含めることだと思います。
デフォルト値を指定するという目的に反するとは思わない。デフォルト値はコードを呼び出すのに便利ですが、テストでは明示的にする必要があると思います。 bool
パラメーターの指定は省略できます。将来、誰かがb
のデフォルト値をtrue
に変更するとどうなりますか?これはテストの失敗につながりますが(当然のことながら)、b
はfalse
であるという隠された仮定のため、修正がより困難になります。 bool
パラメーターを明示的に指定することには別の利点があります。テストの可読性が向上します。それらを通過する人は、2つのパラメーターを受け入れるFoo
関数が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
{
...
}
}
今日この問題が発生したばかりで、Moqはこのユースケースをサポートしていません。したがって、この場合はメソッドをオーバーライドするだけで十分だと思われます。
public interface IFoo
{
bool Foo(string a);
bool Foo(string a, bool b);
}
これで両方の方法が利用可能になり、この例は機能します:
var mock = new Mock<IFoo>();
mock.Setup(mock => mock.Foo(It.IsAny<string>())).Returns(false);