Unity IoC - 单元测试类型的注册是否正确

问题描述 投票:3回答:2

我有一个非常简单的微服务,在大多数情况下,我不运行,而是依靠单元测试和集成测试来确认实现是正确的,并将工作。最近,我进行了更改,单元测试通过,因此部署到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中包装依赖项的寄存器并记录事件失败,但我想在部署之前捕获它。

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

c# unit-testing unity-container
2个回答
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);
}

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


0
投票

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

[Test]
public void AssertThatDependenciesCorrectlyMap()
{
    Assert.DoesNotThrow(() => 
    {
        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)),
                ));
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.