[解決済み] Moqでクラスをモックするとき、特定のメソッドだけをCallBaseする方法は?
質問
モックには本当に感謝しています。
Loose
期待値が設定されていないときにデフォルト値を返すモッキングの動作です。これは便利でコードの節約になりますし、安全対策としても機能します。ユニットテスト中に依存関係が意図せず呼び出されることはありません(それらが仮想である限り)。
しかし、テスト対象のメソッドがたまたま仮想であった場合、これらの利点をどのように保てばよいのか、私は混乱しています。
この場合、私は
する
は、クラスの残りの部分を緩くモック化したまま、そのメソッドの実際のコードを呼び出したいのです。
私が検索して見つけたのは、「Security」(セキュリティ)を設定することです。
mock.CallBase = true
を使用して、そのメソッドが確実に呼び出されるようにします。しかし、それはクラス全体に影響します。なぜなら、呼び出しの依存性を隠すクラスの他のすべてのプロパティとメソッドについてジレンマに陥るからです。
- 依存性を隠すすべてのプロパティとメソッドのスタブをセットアップする -- テストがそれらの依存性を気にする必要がないと考えていても、です。
- スタブのセットアップを忘れないように(そして、将来的に新しい依存関係が追加されないように) -- ユニットテストが本当の依存関係にぶつかるリスクを考えてください。
私が欲しいと思っているのは、次のようなものです。
mock.Setup(m => m.VirtualMethod()).CallBase();
を呼び出すと
mock.Object.VirtualMethod()
Moqは実際の実装を呼び出すのです。
Q: Moqで、いくつかの依存関係をスタブするためにクラスをモックしたとき、仮想メソッドをテストする方法はありますか?I.e. CallBase=true そして、すべての依存関係をスタブする必要がありますか?
説明のためのコード例
(MSTest, InternalsVisibleTo DynamicProxyGenAssembly2 を使用)
次の例では
TestNonVirtualMethod
は通るが
TestVirtualMethod
は失敗し、null を返します。
public class Foo
{
public string NonVirtualMethod() { return GetDependencyA(); }
public virtual string VirtualMethod() { return GetDependencyA();}
internal virtual string GetDependencyA() { return "! Hit REAL Dependency A !"; }
// [... Possibly many other dependencies ...]
internal virtual string GetDependencyN() { return "! Hit REAL Dependency N !"; }
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestNonVirtualMethod()
{
var mockFoo = new Mock<Foo>();
mockFoo.Setup(m => m.GetDependencyA()).Returns(expectedResultString);
string result = mockFoo.Object.NonVirtualMethod();
Assert.AreEqual(expectedResultString, result);
}
[TestMethod]
public void TestVirtualMethod() // Fails
{
var mockFoo = new Mock<Foo>();
mockFoo.Setup(m => m.GetDependencyA()).Returns(expectedResultString);
// (I don't want to setup GetDependencyB ... GetDependencyN here)
string result = mockFoo.Object.VirtualMethod();
Assert.AreEqual(expectedResultString, result);
}
string expectedResultString = "Hit mock dependency A - OK";
}
解決方法は?
Lunivoreさんの回答は、書かれた時点では正しかったと思います。
Moqの新しいバージョン(2013年のバージョン4.1以降だと思います)では、あなたが提案する構文そのもので、あなたが望むことを行うことが可能です。つまり、以下の通りです。
mock.Setup(m => m.VirtualMethod()).CallBase();
の基本実装を呼び出すためのルースモックを設定しています。
VirtualMethod
を返すだけでなく
default(WhatEver)
しかし、このメンバー (
VirtualMethod
) のみです。
ユーザーのBornToCodeがコメントで指摘しているように、この方法はメソッドに
戻り値型
void
. を指定すると
VirtualMethod
が非voidの場合
Setup
を呼び出すと
Moq.Language.Flow.ISetup<TMock, TResult>
を継承しています。
CallBase()
メソッドから
Moq.Language.Flow.IReturns<TMock, TResult>
. しかし、このメソッドが無効である場合、私たちは
Moq.Language.Flow.ISetup<TMock>
の代わりに、必要な
CallBase()
というメソッドがあります。
更新しました。
andrew.rockwellは以下のように書いています。
void
というメソッドがあり、どうやらバージョン4.10(2018年~)で修正されたようです。
関連
-
[解決済み] Invalid setup on a non-virtual (overridable in VB) member..." というメッセージのExceptionが発生するのはなぜですか?
-
[解決済み] プライベートメソッド、フィールド、インナークラスを持つクラスをテストするにはどうすればよいですか?
-
[解決済み] Mockitoでvoidメソッドをモックする方法
-
[解決済み] フェイク、モッキング、スタビングの違いとは?
-
[解決済み] ユニットテストは努力に値するか?[クローズド]
-
[解決済み] ASP.NET CoreでILoggerを使ったユニットテストを行う方法
-
[解決済み] モックオブジェクトは何のためにあるのか?
-
[解決済み] ファイルシステムに依存するコードの単体テスト
-
[解決済み] スタブとは?
-
[解決済み] Enzyme - How to access and set <input> value?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] モッキングとは?
-
[解決済み] ユニットテストとインテグレーションテストの違いは何ですか?[重複あり]
-
[解決済み】ユニットテストを実行せずにMavenプロジェクトをビルドする
-
[解決済み】mochaのテスト用ディレクトリを指定するには?
-
[解決済み] Spring Dataのリポジトリをテストするには?
-
[解決済み] Goでテストカバレッジを測定する方法
-
[解決済み] ファイルシステムに依存するコードの単体テスト
-
[解決済み] GTestとCMakeを使った作業の始め方
-
[解決済み] "エラー。Karma-Jasmineのユニットテストケースを書いているときに「No provider for router」というエラーが発生しました。
-
[解決済み] Go の testing パッケージを使用してテストのセットアップを行うにはどうすればよいですか?