Unity IoC - 单元测试正确

时间:2018-01-03 13:33:11

标签: c# unit-testing unity-container

我有一个非常简单的微服务,在大多数情况下,我不会运行,而是依靠单元测试和集成测试来确认实现是否正确并且可行。最近,我进行了更改,单元测试通过,因此部署到CI环境(稍后运行集成测试,可以告诉我问题是什么)。在我的统一组件的注册中,我创建了一个工厂并传递了一组数组参数,例如:

var container = new UnityContainer();

container.RegisterType<IMyType, MyImpl1>(nameof(MyImpl1));
container.RegisterType<IMyType, MyImpl2>(nameof(MyImpl2));
container.RegisterType<IMyType, MyImpl3>(nameof(MyImpl3));

container.RegisterType<MyFactory>(
        new InjectionConstructor(new ResolvedArrayParameter<IMyType>(
            new ResolvedParameter<IMyType>(nameof(MyImpl1)),
            new ResolvedParameter<IMyType>(nameof(MyImpl2)),
            new ResolvedParameter<ISomeOtherType>(nameof(MyImpl3)),
        ));

对于那些老鹰眼的读者,你会发现最后一个已解决的参数的错误,这基本上是我想测试的 - 当然,我可以在try-catch中包装依赖项的寄存器并记录发生故障但我想在部署之前捕获它。

所以,我的问题很简单(或者不是,我的谷歌搜索证明是一次大规模的失败),我如何检查依赖项是否正确解析并模拟应用程序的运行?

2 个答案:

答案 0 :(得分:3)

一种方法是首先将依赖注册移动到自己的类中,无论该容器支持的特定版本是什么 - Windsor Facility,Unity扩展等。

这意味着我们不会在测试中复制容器设置。相反,我们会测试我们在应用程序中实际使用的相同容器设置。

public class MyUnityExtension : UnityContainerExtension
{
    protected override void Initialize()
    {
        Container.RegisterType<IMyType, MyImpl1>(nameof(MyImpl1));
        Container.RegisterType<IMyType, MyImpl2>(nameof(MyImpl2));
        Container.RegisterType<IMyType, MyImpl3>(nameof(MyImpl3));
    }
}

如果您希望应用程序提供特定于环境的值,您可以在接口或类中定义这些值并将其添加到构造函数中,然后根据容器设置中的需要使用这些设置中的连接字符串等值。

public class MyUnityExtension : UnityContainerExtension
{
    private readonly ISettings _settings;

    public MyUnityExtension(ISettings settings)
    {
        _settings = settings;
    }

    ...etc
}

现在,在您的单元测试中,您可以将扩展程序添加到容器中,并测试您是否能够解析特定的依赖项。

using (var container = new UnityContainer())
{
    var extension = new MyUnityExtension();
    container.AddExtension(extension);
    var resolved = container.Resolve<IMyType>();
    Assert.IsNotNull(resolved);
}

与此同时,您可以打包依赖注册,以便托管应用程序只能提供一些特定于环境的值,而不必配置容器本身。

答案 1 :(得分:0)

因此,根据@ camilo-terevinto的注释,当您注册依赖项时,它会抛出异常 - 下面使用nunit测试的简化版本:

import java.util.zip.ZipEntry;