1. ホーム
  2. c#

[解決済み] オプションの引数を明示的に指定したりオーバーロードを使用せずに、シグネチャにオプションの引数を持つメソッドをMoqするにはどうすればよいですか?

2022-07-03 16:23:59

質問

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

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 リリース (それがいつであれ) に割り当てられているようです。

私の質問は、上記がすぐに修正されそうにないことを考えると、私はどうしたらよいでしょうか。私の選択肢は、モックするたびにオプション パラメーターのデフォルト値を明示的に設定する (これは、最初の場所で 1 つを指定するポイントを打ち消すようなものです) か、bool のないオーバーロードを作成する (C# 4 以前なら行っていたように) ことのみでしょうか?

または、この問題を克服するためのより巧妙な方法に出会ったことがありますか?

どのように解決するのですか?

今のところ、唯一の選択肢は、明示的に bool のセットアップで Foo .

デフォルト値を指定する目的は破たんしていないと思います。デフォルト値はコードを呼び出すための便宜的なものですが、テストでは明示的に指定するべきだと思うのです。例えば bool パラメータを指定しないとします。のデフォルト値を変更した場合、どうなるでしょうか? btrue ? これはテストの失敗を招きますが(そしてそれは当然です)、以下のような隠された前提があるため、修正がより困難になります。 bfalse . を明示的に指定することで bool パラメータを明示的に指定することで、テストの可読性を高めることができます。テストの読みやすさが向上します。 Foo 関数があることがすぐにわかるでしょう。これが、少なくとも私の2セントです :)

モックを作るたびにそれを指定することについては、コードを重複させないことです:モックを関数の中で作成または初期化し、変更のポイントが1つになるようにします。本当にそうしたいのであれば、Moq の明らかな欠点を克服するために Foo のパラメータをこの初期化関数に複製します。

public void InitFooFuncOnFooMock(Mock<IFoo> fooMock, string a, bool b = false)
{
    if(!b)
    {
        fooMock.Setup(mock => mock.Foo(a, b)).Returns(false);
    }
    else
    {
        ...
    }
}