3

以下のようなAutofacモジュールがあります

    public class ServiceInjector:Module
    {
        protected override void Load(ContainerBuilder builder)
            {
                // many registrations and type looking up here
                ...
                // One of the registration, say t which is found
                // in above looking, is a resource consuming type

                builder.RegisterType(t).As<ITimeConsume>();

                // ...
            }
    }

このモジュールは ServiceClass で使用されます。

public class ServiceClass
{
    static IContainer _ioc;
    public ServiceClass()
    {
        var builder = new ContainerBuilder();
        builder.RegisterModule<ServiceInjector>();

        _ioc = builder.Build();     
    }

    public void InvokeService()
    {
        using(var scope = _ioc.BeginLifetimeScope())
        {
            ITimeConsume obj = scope.Resolve<ITimeConsume>(...);

            var result = obj.DoTimeConsumingJob(...);

            // do something about result here ...
        }    
    }
}

私の質問は、(Moq) ITimeConsume クラスをモックして ServiceClass をテストするにはどうすればよいですか? ここで、以下のテストを書きます。

public void Test()
{
    Mock<ITimeConsume> moc = GetMockObj(...);

    // How can I inject moc.Object into ServiceInjector module,
    // so that ServiceClass can use this mock object ?
}

途中でこれが不可能な場合、注入できる時間のかかるクラスをモックするためのより良い設計は何ですか?

**

アップデート:

** @dubs と @OldFox のヒントに感謝します。重要なのは、Autofac インジェクターを内部制御ではなく外部で初期化する必要があることだと思います。そこで、Autofac.ILifetimeScope の「 On Fly 」ビルド機能を活用し、LifeTime スコープ パラメーターを使用して ServiceClass コンストラクターを設計します。この設計により、以下の例のように、単体テストで任意のサービスをオンフライで登録できます。

using(var scope = Ioc.BeginLifetimeScope(
    builder =>  builder.RegisterInstance(mockObject).As<ITimeConsume>())
4

2 に答える 2

4

現在の設計では、モック オブジェクトを注入できません。最小限の変更で最も簡単な解決策は、InternalCto'r をに追加することServiceClassです。

internal ServiceClass(IContainer ioc)
{
    _ioc = ioc;     
}

次に、属性InternalsVisibleToを使用して、テスト クラスで C`tor を使用できるようにします。

Arrange/setup/testInit フェーズで、モック オブジェクトを含むコンテナーでテスト対象のクラスを初期化します。

    [SetUp]
    public void TestInit()
    {
        Mock<ITimeConsume> moc = GetMockObj(...);
        builder.RegisterInstance(moc).As<ITimeConsume>();
        ...
        ...
        _target = new ServiceClass(builder.Build());
    }
于 2015-07-14T10:00:41.270 に答える
1

個人的には、複数のコンテナ インスタンスがあります。エンドポイントごとに 1 つ。

テスト プロジェクト

public class AutofacLoader
{
    public static void Configure()
    {
        var builder = new ContainerBuilder();

        builder.RegisterModule<ServiceProject.ServiceInjector>();
        builder.RegisterModule<LocalTestProject.AutofacModule>();

        Container = builder.Build();
    }

    public static IContainer Container { get; set; }
}

ローカル テスト プロジェクトの autofac モジュールは、サービス プロジェクト モジュールを特定の登録で自由にオーバーライドできます。

複数のコンポーネントが同じサービスを公開している場合、Autofac は最後に登録されたコンポーネントをそのサービスのデフォルト プロバイダーとして使用します: http://autofac.readthedocs.org/en/latest/register/registration.html#default-registrations

テストクラス

public void Test()
{
    AutofacLoader.Configure();

    var x = AutofacLoader.Container.Resolve<ITimeConsume>();
}
于 2015-07-14T10:02:29.593 に答える