AutoConfiguredMoqCustomizationを使用する場合、使用されたフィクスチャによって返される値がキャッシュされ、呼び出しごとに同じ値が返されます(これがMockType.ReturnsUsingContextまたは他の場所で行われるかどうかはわかりませんが、コメントが表示されます104行目)。
それをオーバーライドすることがわかった唯一の方法は、問題のモックのFrozenインスタンスをテストメソッドに渡し、フィクスチャを呼び出す関数でセットアップをオーバーライドすることです。
someMock.Setup(it => it.SomeMethodReturningAString()).Returns(() => fixture.Create<string>())
AutoFixtureから値が必要になるたびにフィクスチャを呼び出すように自動生成されたモックを構成する、各呼び出しを手動で設定する以外に、より一般的でスマートな方法はありますか?
結果値をキャッシュする背後にある考え方は、すべてのメソッドをデフォルトで_純粋_にすること
テスト対象のシステムが純粋関数を期待しているが、不純な関数が与えられている場合、テストの結果、誤検出が発生する可能性があります。 例えば
// This method will return the expected result *if* `GetInt` is pure.
int Double(IDependency dep) {
return dep.GetInt() + dep.GetInt();
}
Assert.Equal(dep.GetInt * 2, Double(dep));
一方、テスト対象のシステムが純度を想定していない場合は、純粋または不純な機能を与えても違いはありません。
したがって、この機能を実装したとき、デフォルトで純粋関数を使用するのは理にかなっています。
AutoFixtureから値が必要になるたびにフィクスチャを呼び出すように自動生成されたモックを構成する、各呼び出しを手動で設定する以外に、より一般的でスマートな方法はありますか?
_one_メソッドに対してこれを行う必要があるが、複数のテストにわたって、再利用可能なIConfiguration
ます。
複数のテストにわたって、すべてのメソッドに対してこれを実行する場合は、もう少し作業が必要になります。
ReturnsUsingContext
新しい実装を定義します(IIRC、現在の実装をコピーして104行目を削除できます)MockVirtualMethodsCommand
を再定義し、 ReturnsUsingContext
への呼び出しを新しいメソッドへの呼び出しに置き換えます。AutoConfiguredMoqCustomization
を再定義し、 MockVirtualMethodsCommand
のインスタンス化を新しいクラスのインスタンス化に置き換えます。この動作を構成可能にする方法を考えることもできますが、これを正当化するのに十分な需要があるかどうかはわかりません。 私の意見では、このような変更を軽視すべきではありません。きめ細かいカスタマイズは、偶発的な複雑さにつながる可能性があります。 @ploeh 、これについてどう思いますか?
テストダブルは、戻り値を取得するためにAutoFixtureにコールバックするように構成されていると思ったことを認めます。 AutoFixtureには(フリーズ機能を介した)ライフタイム管理メカニズムがすでに備わっているため、 AutoConfiguredMoqCustomization
が独自のライフタイムマネージャーを実装し、AutoFixture自体が提供するコントロールサーフェスをオーバーライドするのは少し驚きです。
それは非常に良い点です、私はそのようにFreeze
について考えたことはありませんでした。 カスタマイズの動作を変更することは、重大な変更になると思います... AutoFixture v4で変更する必要があると思いますか?
それは、私たちが文書化した、またはテストで何らかの形で「約束された」動作ですか?
驚いたことに、いいえ。 私はこれをカバーしたとかなり確信していましたが、カバーしなかったようです。 少なくとも、これをカバーするテストは見つかりませんでした。その行を削除しても、テストは失敗しませんでした。 ただし、IMO、それはまだ観察可能な動作であり、これに依存するコードが存在する可能性があります...
フェアポイント。 ここで1つの値に設定し、AutoFixture 4に移行するときにそれを切り替える構成値である可能性がありますか?
同意しました。 この文脈で、「構成値」とは正確にはどういう意味ですか? MockType
クラス内の定数にそれを持ち上げるだけで十分でしょうか? 例: private const bool cacheReturnValues = true
、次にif(cacheReturnValues) /**/
それはちょっと使い捨てのコメントだったと私は認めます、それで私はそれがあまり多くの変更なしで実際に可能であるかどうかわかりません。 しかし、私が意味したのはこれでした:
@andreasnilsenは今すぐ動作を変更したいと思っていますが、それが@ andreasnilsenに動作を変更する方法を提供します。
AutoFixture 4を導入するときは、デフォルトの構成を変更します。これにより、デフォルトの動作では、戻り値はキャッシュされません。 または、単にそのオプションを削除するだけかもしれません...
ブールcacheReturnValues
ようなものは、それを行う1つの方法である可能性がありますが、クライアントが値を変更できるようにする必要があるため、 private
にすることはできません。
(我々は唯一、正確に二つの値があるように起こっていることを絶対的に一定している場合を除きまた、我々は考慮すべきであるenum
の代わりにbool
。)
ああ、私は最初、v4で簡単に見つけて変更できる内部フラグを意味していると思いました。
頭に浮かぶ最初の2つのアプローチは次のとおりです。
AutoConfiguredMoqCustomization
のコンストラクターにブールパラメーター(下位互換性のためにオプション)を追加するだけで、 MockVirtualMethodsCommand
と内部MockType.ReturnsUsingContext
伝播されます。 これはどうやら:後悔して後回しになるような設計上の決断には警戒しているので、このプロジェクトを維持するための専門知識/経験をいただければ幸いです。
私は戦略のようなものを考えていました...
もちろんです! 私は「構成値」に固執し、一歩後退するのを忘れたと思います。
返信が遅くなってすみません、私は圧倒されました-私はこれをすぐに見て、デザイン提案で戻ってきます。
最近、カスタマイズの調整にプロパティを使用するために、カスタマイズのリファクタリングを実行しました。 潜在的に、この機能は次のように制御できます(より適切な設定名を見つけてください)。
c#
new AutoMoqCustomization { CacheCallResults = false }
内部的には、上記でアドバイスしたようなさまざまな戦略を介してそれを実装できます。
これを実装するのは比較的簡単なはずなので、ジャンプインタグでマークします。
@zvirjaは私を少し助けてくれませんか、私はこれに
@micheleissa興味を持ってくれてありがとう! AutoMoq
ソースコードを読んでデバッグし、内部の仕組みを理解することをお勧めします。 とても小さいので、それほど時間はかからないはずです...
より具体的な質問がある場合は、😉までお問い合わせください
最も参考になるコメント
テストダブルは、戻り値を取得するためにAutoFixtureにコールバックするように構成されていると思ったことを認めます。 AutoFixtureには(フリーズ機能を介した)ライフタイム管理メカニズムがすでに備わっているため、
AutoConfiguredMoqCustomization
が独自のライフタイムマネージャーを実装し、AutoFixture自体が提供するコントロールサーフェスをオーバーライドするのは少し驚きです。