如何使用命名组件对此IoC注册进行单元测试? (Autofac)

时间:2010-11-28 14:28:56

标签: unit-testing ioc-container autofac

我正在考虑将一些复杂的创建代码转换为使用IoC容器Autofac,因为我非常相信TDD,我正在编写模块配置的单元测试。

大多数功能都很容易测试,例如。

var obj = container.Resolve<IThing>();
Assert.IsInstanceOfType(obj, typeof(ThingImplementer));

但是我们有很多案例,我们有多个相同接口的实现者,不同的实现者被传递给不同的具体类。我已经通过使用命名注册解决了这个问题,例如

builder.RegisterType<ThingImplementer>().Named<IThing>("Implementer1");
builder.RegisterType<OtherImplementer>().Named<IThing>("Implementer2");
builder.Register(c => new Foo(c.ResolveNamed<IThing>("Implementer1"))).As<IFoo>();

我无法弄清楚的是编写单元测试以确保Foo获得ThingImplementer而不是OtherImplementer的简单方法。我想知道是否值得付出努力,我们确实有高级集成测试来涵盖这一点,但他们没有提供单元测试所做的文档或重构好处。

你会为此写一个单元测试吗? 如果是这样,怎么样?

2 个答案:

答案 0 :(得分:7)

您通常不会在单元测试中测试容器的配置。在您的单元测试环境中,您不使用容器来注入任何依赖项(您手动执行此操作),如果您这样做,您将注入假对象,而不是真实/生产类型。因此,容器配置通常不为您的单元测试所知。

我倾向于做的有时候是测试容器是否能够创建应用程序的根类型(例如MVC应用程序的控制器类,或WebForms应用程序的Page类)。因为容器将实例化对象图,所以我会很好地了解容器是否配置正确。但是,如果容器返回正确的实现,我永远不会感兴趣。大多数情况下,甚至只有一个注册接口的实现可供应用程序根访问,因此几乎不会出错。

如果您想测试容器配置,可能过于复杂,您应该尝试简化应用程序设计,以便简化注册。

答案 1 :(得分:2)

这里没什么新东西,只是史蒂文积分的延伸。

史蒂文说,这绝对不是单元测试。您也许可以将其视为学习测试。看看Ninject测试套件 - 它显示了他们如何进行这样的测试(但记住他们正在编写一个Container)。我认为autofac有类似的测试。

话虽如此,如果你觉得有趣的行为并且它不会变得不稳定,那么将它粘贴到集成套件中并没有坏处。

关于它是外在的这一事实的另一点也非常有效 - 请参阅Onion Architecture的概念