コンストラクターにパラメーターがある場合のMoqによるオブジェクトのモック


92

moqを使用してモックしようとしているオブジェクトがあります。オブジェクトのコンストラクターには必須パラメーターがあります。

public class CustomerSyncEngine {
    public CustomerSyncEngine(ILoggingProvider loggingProvider, 
                              ICrmProvider crmProvider, 
                              ICacheProvider cacheProvider) { ... }
}

今、私はmoqのv3 "setup"またはv4 "Mock.Of"構文のいずれかを使用してこのオブジェクトのモックを作成しようとしていますが、これを理解できません...私が試みているすべてが検証されていません。これが私がこれまで持ってきたものですが、最後の行はモックではなく実際のオブジェクトを与えています。私がこれをしている理由は、確認したいCustomerSyncEngineのメソッドが呼び出されているためです...

// setup
var mockCrm = Mock.Of<ICrmProvider>(x => x.GetPickLists() == crmPickLists);
var mockCache = Mock.Of<ICacheProvider>(x => x.GetPickLists() == cachePickLists);
var mockLogger = Mock.Of<ILoggingProvider>();

// need to mock the following, not create a real class like this...
var syncEngine = new CustomerSyncEngine(mockLogger, mockCrm, mockCache);

呼び出されることを確認するサンプルメソッドを提供できますか?
Ciaran

4
したがって、インターフェイスではなくクラスへの依存関係がある場合、それらの依存関係さえもモックする必要がありますが、これは再帰的に低下します。結局、コードにインターフェイスが必要ない場合でも、コードをテスト可能な状態に保つために、いくつかのインターフェイスを使用する必要があります。インターフェイスが多すぎると、具象クラスをあざけるよりも臭いが大きいと思います...
Tarion

回答:


34

最後の行は、CustomerSyncEngineをモックするのではなく、新しいキーワードを使用しているため、実際のインスタンスを提供しています。

あなたは使うべきです Mock.Of<CustomerSyncEngine>()

コンクリート型のモッキングの唯一の問題は、Moqが(パラメーターのない)パブリックデフォルトコンストラクターを必要とすること、またはコンストラクターの引数指定でMoqを作成する必要があることです。http://www.mockobjects.com/2007/04/test-smell-mocking-concrete-classes.html

最善の方法は、クラスを右クリックして、抽出インターフェースを選択することです。


3
問題に関しては、代替案はAutoMockingコンテナを使用することです。私のお気に入りは、Machine.FakesとMachine.Specificationsの組み合わせです。オートモッキングコンテナーを使用すると、小さい表面積を簡単にテストできます。Andrewがメソッドをテストする必要があると仮定します。従来のモッキング実装でのCustomerSyncEngine使用のみをICrmProvider3つのインターフェースすべてに提供する必要があるのに対し、自動モッキングコンテナーでは1つしか提供できません。
Chris Marisic 2014年

73

最後の行を

var syncEngine = new Mock<CustomerSyncEngine>(mockLogger, mockCrm, mockCache).Object;

そしてそれはうまくいくはずです


3
このコメントが私の回答にどのように当てはまるかわからないですか?
Suhas 2013年

2
mockLoggerなどがObjectプロパティを持たないという例外をスローするとコンパイルエラーが発生するため
Justin Pihony 2013年

2
OPはMock.Of <T>()を使用してロガー、crm、およびキャッシュタイプのモックを作成するため、返されるオブジェクトはMock <T>ではなくTとして返されます。そのため、CustomerSyncEngineのMockにmockLogger.Objectなどを渡す場合は必要ありません。@ JustinPihonyで述べたように、設計時エラーが表示されます。
ジョシュガスト2018

1
@suhas彼のはずではありませんnew Mock<CustomerSyncEngine>(new object[]{mockLogger, mockCrm, mockCache}).Object;
GiriB

モックはParamsで定義されているため、@ GiriBは不要ですが、可能です。公共モック(paramsはオブジェクト[]引数)
イジーHerník
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.