1

特定の Unity IoC オブジェクトがインスタンス化されたことを確認する単体テストを作成したいと考えています。

たとえば、これが私がテストしているクラスです。

using Microsoft.Practices.Unity;
using System.Threading;

namespace Client.Engine
{
    public sealed class Uploader : IUploader
    {
        private readonly IUnityContainer _container;

        public Uploader(IUnityContainer container)
        {
            _container = container;
        }

        public void PerformUpload(CancellationToken token, int batchSize)
        {
            token.ThrowIfCancellationRequested();
            _container.Resolve<IUploadModule>("Clients").Upload(token, batchSize);

            token.ThrowIfCancellationRequested();
            _container.Resolve<IUploadModule>("Patients").Upload(token, batchSize);
        }
    }
}

そして、ここに私が設定した単体テストがあります

[TestClass()]
public class UploadClientsTests : UploadModuleTestsBase
{
    [TestMethod()]
    public override void UploaderRegrestrationTest()
    {
        PerformRegistrationTest("Clients");
    }
}

[TestClass()]
public class UploadPatientsTests : UploadModuleTestsBase
{
    [TestMethod()]
    public override void UploaderRegrestrationTest()
    {
        PerformUpladerRegistrationTest("Patients");
    }
}

public class UploadPatientsTests : UploadModuleTestsBase
{
    protected static void PerformUpladerRegistrationTest(string moduleName)
    {
        var container = new UnityContainer();
        var mocker = new AutoMoqer(container);
        var random = new Random();
        int batchSize = random.Next(int.MaxValue);
        var token = new CancellationToken();

        var uploadModuleMock = new Mock<IUploadModule>();
        uploadModuleMock.Setup(module => module.Upload(token, batchSize)).Verifiable();

        container.RegisterInstance(typeof(IUploadModule), moduleName, uploadModuleMock.Object, new ContainerControlledLifetimeManager());
        container.RegisterInstance(typeof(IUploadModule), Mock.Of<IUploadModule>());
        var uploader = mocker.Resolve<Uploader>();
        uploader.PerformUpload(token, batchSize);

        uploadModuleMock.Verify();
    }
}

私が遭遇した問題は、名前付きの型が利用できない場合、Unity 2.0 がデフォルトのインスタンスにフォールバックしないことです。したがって_container.Resolve<IUploadModule>("Patients")、クライアント テストが完全に機能する行をコメント アウトすると _container.Resolve<IUploadModule>("Clients")、患者テストが完全に機能する行をコメント アウトすると、両方が共存できるようにする方法がわかりません。


編集: 通常の操作では、このように 2 つのオブジェクトを並べ替えています。

public static Bootstrap(IUnityContainer container)
{
    container.RegisterType<IUploadModule, UploadClients>("Clients", new HierarchicalLifetimeManager());
    container.RegisterType<IUploadModule, UploadPatients>("Patients", new HierarchicalLifetimeManager());
}
4

2 に答える 2

3

IUnityContainer実際の UnityContainer を使用する代わりに、実際に直接モックしてみませんか?

メソッドの単体テストの観点からはPerformUpload、実際にResolve<>Uploadメソッドの両方が呼び出され、対応するパラメーターが指定されていることのみをアサートする必要があります。Unity が解決する方法の実際の内部構造ではありません。

実際、への依存関係を削除して、IUnityContainer代わりにコンストラクターにファクトリー メソッドを受け取り、Unity に登録することもできます。私はそのような依存関係を避ける傾向があり、ファクトリを として直接宣言しFunc<string, IUploadModule>ます。

次の例はテストされていませんが、次のようなものが機能する可能性があります。

container.RegisterType<Func<string, IUploadModule>>(new InjectionFactory(c => 
    new Func<string, IUploadModule>(name => 
        c.Resolve<IUploadModule>(name)
        )
    )
);

追加登録です。また、アップローダーを現在と同じように登録する必要があります。

それを登録すると、コンストラクターをFunc<string, IUploadModule>パラメーターとして使用できます。

public Uploader(Func<string, IUploadModule> factory)
{
    _factory = factory;
}

次の方法で呼び出して、アップローダーを取得します。

_factory("Patients");
于 2014-02-22T00:22:34.443 に答える