web-dev-qa-db-ja.com

Moqを使用して内部コンストラクターで型をモックする

Microsoft SyncFrameworkのクラスをモックしようとしています。内部コンストラクターのみがあります。私が以下を試すとき:

_var fullEnumerationContextMock = new Mock<FullEnumerationContext>();
_

このエラーが発生します:

System.NotSupportedException:親にはデフォルトのコンストラクターがありません。デフォルトのコンストラクターは明示的に定義する必要があります。

これはスタックトレースです:

System.Reflection.Emit.TypeBuilder.DefineDefaultConstructorNoLock(MethodAttributes属性)System.Reflection.Emit.TypeBuilder.DefineDefaultConstructor(MethodAttributes属性)System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()System.Reflection.Emit.TypeBuilder.CreateType()Castle。 DynamicProxy.Generators.Emitters.AbstractTypeEmitter.BuildType()Castle.DynamicProxy.Generators.ClassProxyGenerator.GenerateCode(Type [] interfaces、ProxyGenerationOptions options)Castle.DynamicProxy.DefaultProxyBuilder.CreateClassProxy(Type classToProxy、Type [] additionalInterfacesToProxy、ProxyGenerationOptions options)Castle。 DynamicProxy.ProxyGenerator.CreateClassProxyType(Type classToProxy、Type [] additionalInterfacesToProxy、ProxyGenerationOptions options)Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy、Type [] additionalInterfacesToProxy、ProxyGenerationOptions options、Object []コンストラクター引数、IInterceptor []インターセプター)Castle.DynamicProxy。 ProxyGenerator.Create ClassProxy(Type classToProxy、Type [] additionalInterfacesToProxy、ProxyGenerationOptions options、IInterceptor []インターセプター)Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy、Type [] AdditionalInterfacesToProxy、IInterceptor []インターセプター)Moq.Mock1.<InitializeInstance>b__0() Moq.PexProtector.Invoke(Action action) Moq.Mock 1.InitializeInstance ()

どうすればこれを回避できますか?

30
Tom Robinson

Moqはその型のオブジェクトをインスタンス化できないため、パブリックコンストラクターを持たない型をモックすることはできません。テストしようとしているものに応じて、いくつかのオプションがあります。

  1. ファクトリオブジェクトまたはFullEnumerationContextのインスタンスを取得する他の方法がある場合は、おそらくそれを使用できます(申し訳ありませんが、同期フレームワークに精通していません)
  2. プライベートリフレクションを使用してFullEnumerationContextをインスタンス化することはできますが、その場合、メソッドをモックすることはできません。
  3. テスト対象のコードが呼び出すことができるモック可能なインターフェイスやラッパーオブジェクトを導入できます。ランタイム実装は実際のFullEnumerationContextに委任しますが、テスト時実装は必要なアクションを実行します。
20
marcind

私はMoqの専門家ではありませんが、コンストラクターの引数を指定する必要があると思います。 Rhino Mocksでは、次のように指定します。

var fullEnumerationContextMock = new Mock<FullEnumerationContext>(arg1, arg2);

それはおそらくMoqでも同様です。

5
Grzenio

marcind からの回答に基づいて、モックするインターフェイス(IFullEnumerationContext)を作成しました。次に、テストしようとしているメソッドのオーバーロードが2つあり、1つはFullEnumerationContextIFullEnumerationContextを取る別のもの。気分は良くありませんが、機能します。より良い提案や改善があれば歓迎します。

public override void EnumerateItems(FullEnumerationContext context)
{
    List<ItemFieldDictionary> listItemFieldDictionary = EnumerateItemsCommon();
    context.ReportItems(listItemFieldDictionary);
}

public void EnumerateItems(IFullEnumerationContext context)
{
    List<ItemFieldDictionary> listItemFieldDictionary = EnumerateItemsCommon();
    context.ReportItems(listItemFieldDictionary);
}
2
Tom Robinson

実際にできます。 AssemblyInfo.csファイルを開き、最後に次の行を追加します。

[Assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

1
fhnaseer

テスト対象システムプロジェクトでは、次のものが必要です。

  • protected internal SUTクラスでのコンストラクターの可視性(例:FullEnumerationContext
  • AssemblyInfo.cs内部をテストプロジェクトに公開する必要があります。

    [Assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
    
0
Mariano Desanze