您是否应该对将组件注册到 IoC 容器中的代码进行单元测试?
如果是这样,怎么做?
在我的测试项目中运行 IoC 容器对我来说感觉有点不对劲。我还注意到,大多数由未解决的依赖关系引起的错误都是由解决依赖关系的顺序引起的,这很难正确测试,也不是我想做的单元测试。
通常我在类的初始化例程中使用 Debug.Assert 语句。这为我提供了一个针对 IoC 相关错误的预警系统,还有助于在我的代码中更好地指定依赖关系。
我对Guice IoC 容器所做的是,首先我使用没有 Guice 的 TDD 为某些功能生成类(这些是单元测试)。然后我使用 Guice 为该功能创建了一个集成测试。此时 IoC 配置(Guice 模块)不完整,因此集成测试将失败。使用 TDD,我逐步添加 IoC 配置,直到集成测试通过。除非需要通过测试,否则我不会添加任何 @Inject 注释、配置行或范围声明。因此,我将进行集成(或验收)测试,以确保 IoC 配置正确且完整。
同样的方法应该适用于任何 IoC 容器或其他系统,它们的配置非常复杂以至于可能会崩溃——除非需要通过测试,否则不要编写任何配置。
在 spring 中,您可以进行单元测试,只需加载应用程序上下文而不断言任何内容。这实际上是一个与自动构建相结合的相当有用的测试,因为 spring 在加载完整上下文时会抱怨很多问题。
@aku、@krosenvold 和 @mookid 为测试依赖项的配置是否正确提供了令人信服的论据。
我不认为这是单元测试。
你在测试什么?您不是在尝试对容器本身进行单元测试(可能不是您编写或维护的代码)。
您要测试的是可以创建特定类型的所有依赖项并且可以解析该类型。这听起来像是在您的持续集成环境中进行的非常有用的系统测试或集成测试。
因此,一旦您拥有通过单元测试的二进制文件,您就可以创建容器并在镜像生产环境的机器上运行容器的设置,并测试容器应该能够解析的每种类型是否都可以实际创建并且它们的所有依赖项都可以实例化。
最好在您已应用最新安装程序的新 VM 中运行它。
它很有用,因为一些依赖注入框架(如 Unity)在选择调用哪个构造函数时有奇怪的规则。我肯定会推荐单元测试,以确保您的类型的注册和创建成功发生。
我在一个 ASP.NET MVC 项目中使用 Windsor,我在其中编写了一个简单的测试来验证所有控制器都可以被实例化(即它们的依赖关系可以被解析)。
我对网站的每个配置(例如“开发”、“测试”、“someProductionSite”等)进行了测试,在其中创建具有该特定配置的 Windsor 容器并循环遍历 IController 的所有非抽象实现,检查我可以解决每个实例。
由于控制器工厂是应用程序的唯一入口点,它会生成一个 container.Resolve(...),所以我 100% 确定所有配置都是有效的。
一般来说,我发现编写作为关于整个系统的断言的测试是非常有用和有价值的。
例如,我还断言所有控制器操作都是虚拟的,这是一个要求,因为我正在使用 Castle 的自动事务管理将控制器操作与事务包围起来。
由于您的组件可能有自己的依赖关系或执行一些初始化,我将使用 UT 来介绍这种情况。
就像是
iocContainer.Register(typeof(MyService1));
service = iocContainer.Get(typeof(MyService));
Debug.AssertNotNull(service);