単体テスト用の一般的なオブジェクトを作成するファクトリを作成したいとします。私はすでにLinq2Sql DataContextをモックアップして、データベースにヒットする代わりにメモリテーブルを返すように、私のテストを設定することができました。 DataContextのは、テーブルの多くが含まれている場合実行時にMoq Setup()を動的に呼び出す
_contactsTable = new InMemoryTable<Contact>(new List<Contact>());
_contactEmailsTable = new InMemoryTable<ContactEmail>(new List<ContactEmail>());
// repeat this for each table in the ContactsDataContext
var mockContext = new Mock<ContactsDataContext>();
mockContext.Setup(c => c.Contacts).Returns(_contactsTable);
mockContext.Setup(c => c.ContactEmails).Returns(_contactEmailsTable);
// repeat this for each table in the ContactsDataContext
これは退屈な取得、私はDataContextのオフすべてのテーブルを取得するためにリフレクションを使用し、単純なファクトリメソッドが役立つかもしれないと思った:
私はこのようにそれを設定しましたpublic static DataContext GetMockContext(Type contextType)
{
var instance = new Mock<DataContext>();
var propertyInfos = contextType.GetProperties();
foreach (var table in propertyInfos)
{
//I'm only worried about ITable<> now, otherwise skip it
if ((!table.PropertyType.IsGenericType) ||
table.PropertyType.GetGenericTypeDefinition() != typeof (ITable<>)) continue;
//Determine the generic type of the ITable<>
var TableType = GetTableType(table);
//Create a List<T> of that type
var emptyList = CreateGeneric(typeof (List<>), TableType);
//Create my InMemoryTable<T> of that type
var inMemoryTable = CreateGeneric(typeof (InMemoryTable<>), TableType, emptyList);
//NOW SETUP MOCK TO RETURN THAT TABLE
//How do I call instance.Setup(i=>i.THEPROPERTYNAME).Returns(inMemoryTable) ??
}
return instance.Object;
}
これまで、私はMock用にセットアップする必要があるオブジェクトを作成する方法を理解しましたが、プロパティ名を渡すMoqのSetup()を動的に呼び出す方法を理解できません。私はInvoke()MoqのSetup()メソッドへのリフレクションを見ていましたが、それは本当に醜い高速でした。
誰も、このようにSetup()とReturns()を動的に呼び出す簡単な方法はありますか?
を編集します。ブライアンの答えが私に届きました。これはどのように動作するのですか:
public static DataContext GetMockContext<T>() where T: DataContext
{
Type contextType = typeof (T);
var instance = new Mock<T>();
var propertyInfos = contextType.GetProperties();
foreach (var table in propertyInfos)
{
//I'm only worried about ITable<> now, otherwise skip it
if ((!table.PropertyType.IsGenericType) ||
table.PropertyType.GetGenericTypeDefinition() != typeof(ITable<>)) continue;
//Determine the generic type of the ITable<>
var TableType = GetTableType(table);
//Create a List<T> of that type
var emptyList = CreateGeneric(typeof(List<>), TableType);
//Create my InMemoryTable<T> of that type
var inMemoryTable = CreateGeneric(typeof(InMemoryTable<>), TableType, emptyList);
//NOW SETUP MOCK TO RETURN THAT TABLE
var parameter = Expression.Parameter(contextType);
var body = Expression.PropertyOrField(parameter, table.Name);
var lambdaExpression = Expression.Lambda<Func<T, object>>(body, parameter);
instance.Setup(lambdaExpression).Returns(inMemoryTable);
}
return instance.Object;
}
ラムダメソッドの3行は、メソッドを作成してから呼び出します。私の答えの例を使ってラムダメソッドを作成し、setupメソッドに渡す必要があります。 –
編集していただきありがとうございます。最初のコードでは、特定のコンテキスト(ContactsDataContext)を持ち、汎用コンテキスト(DataContext)を使用してそのコンテキストに移行します。この問題は、テンプレート化されたクラスに存在するプロパティとData Contextのモックを混在させることです。私はいくつかのコードで私の答えを更新するつもりです。 –
ああ、あなたのコメントは私のためにそれを分類したと思います。モックの代わりにモックを作成する必要がありました。できます! –