1

StructureMap 2.6.4.0 を使用しています。これを使用する主な目的は、テストを簡素化することです。StructureMap のドキュメント ( here ) によると、一時的なモック インジェクション (ObjectFactory.Inject<>()) のための優れた機能があります。

間違っている場合は訂正してください。ただし、その機能についての私の理解は次のとおりです。

  1. コンテナ構成のコードを 1 か所にまとめ、すべての「実際の」実装をそれらのインターフェイスにマッピングします。
  2. すべてのテストを実行する前に、アプリケーションと同じコードに基づいて ObjectFactory を初期化します。
  3. テストで「実際の」実装を「テスト」実装に置き換える必要がある場合、ObjectFactory の Inject メソッドで「テスト」実装を注入します。
  4. 元のマッピングを復元し、注入されたモックを削除するには、ResetDefaults() を呼び出す必要があります。

そして私の問題は4番目のステップにあります。

これが私の問題を示すコード例です。

public interface IValueProvider
{
    string GetValue();
}

public class ValueProvider : IValueProvider
{
    public string GetValue()
    {
        return "Value provider";
    }
}

public class TestValueProvider : IValueProvider
{
    public string GetValue()
    {
        return "Test value provider";
    }
}

class Program
{
    static void Main(string[] args)
    {
        ObjectFactory.Initialize(x => x.For<IValueProvider>().Use<ValueProvider>());

        var valueProvider = ObjectFactory.GetInstance<IValueProvider>();
        Console.WriteLine(valueProvider.GetValue());
        // I will see expected "Value provider"


        ObjectFactory.Inject<IValueProvider>(new TestValueProvider());
        valueProvider = ObjectFactory.GetInstance<IValueProvider>();
        Console.WriteLine(valueProvider.GetValue());
        // I will see expected "Test value provider"


        ObjectFactory.ResetDefaults();
        valueProvider = ObjectFactory.GetInstance<IValueProvider>();
        Console.WriteLine(valueProvider.GetValue());
        // I will see NOT expected "Test value provider".
        // Doesn't ResetDefaults() have to restore a ValueProvider implementation?
    }
}

だから、誰かが私が間違っている場所を教えてもらえますか? それとも、StructureMap のバグでしょうか?

4

1 に答える 1

1

メソッドは、プロファイルを にResetDefaults()切り替えます。あなたの場合、それはすでにありました。を通じて登録されたプラグイン タイプは削除されません。String.EmptyInject<T>(T object)

このInject<T>(T object)メソッドは、オブジェクトを PluginType "T" のデフォルトとして登録します。つまり、具象型である現在のデフォルトをオーバーライドしますValueProvider

StructureMap のドキュメントは古いので、以前のバージョンではドキュメントに記載されているように機能していたと思いますが、現在はそうではありません。

Inject<T>(T object)そのため、実行時に構成済みのプラグイン タイプのデフォルトをオーバーライドする場合、または StructureMap プロファイルを使用する場合にのみ、このメソッドを使用してください。

StructureMap は、コンテナから「取り出し」タイプを削除するいくつかの方法を提供します。それらの1つは次のとおりです。

ObjectFactory.Model.EjectAndRemoveTypes(match =>            
            match != null &&
                   match == typeof (TestValueProvider)
);

このコードは、メソッドによって作成された登録を削除しInject<T>(T object)ますが、 type の既定のインスタンスを元に戻しませんIValueProvider。これは、 の既定のインスタンスがなくなったことを意味しますIValueProvider

したがって、例外ObjectFactory.GetInstance<IValueProvider>()がスローされます。StructureMap Exception Code: 202 No Default Instance defined for PluginFamily ...

ObjectFactory.GetAllInstances<IValueProvider>().First()のインスタンスを返しますValueProvider。あなたが期待するもの。

ここで何をテストしようとしているのかよくわかりませんが、それらが単体テストである場合は、IoC コンテナーの必要性を回避するようにしてください (これは に依存することも意味しますObjectFactory)。コンテナが必要な場合は、IContainer自分で管理および作成できる抽象化を使用してください。これを裏付ける他のSOの質問へのリンクは次のとおりです。

于 2013-11-03T18:53:06.263 に答える