我已经将Unity用于我的上一个项目并且非常高兴。但基准测试让我觉得我可以选择Simple Injector来完成下一个项目。
但是,Simple Injector似乎没有其Container
类的接口。这意味着无论何时我想在方法中使用容器,我都无法模拟容器进行单元测试。
我很困惑一个真正基于接口工作的工具本身不会成为容器的接口。我知道依赖注入的经典方法除了启动之外不需要容器。 (其余的使用构造函数注入。)但是我发现当橡胶碰到道路时并不总是如此。有时你只需要容器就可以在代码中进行“解析”。
如果我使用Simple Injector,那么代码似乎越来越难以进行单元测试。
我是对的吗?或者我错过了什么?
答案 0 :(得分:11)
Simple Injector不包含IContainer
抽象,因为那将是无用的:
Simple Injector定义它是没用的, 因为在这种情况下你的代码仍然依赖于库(因为Simple Injector定义了这个抽象),这会导致供应商锁定,即Simple Injector tries to prevent。
除了应用程序的Composition Root之外,您编写的任何代码都不应该依赖于容器,也不应该依赖于容器的抽象。两者都是Service Locator anti-pattern。
单元测试时不应使用DI库。在单元测试时,您应该在被测试的类中手动注入所有伪造或模拟对象。使用容器只会使事情复杂化。也许您正在使用容器,因为手动创建这些类对您来说太麻烦了。这可能表示您的代码存在问题(您可能违反了Single Responsibility Principle)或您的测试(您可能错过了factory method to create the class under test)。
您可以使用容器进行集成测试,但是您可以 首先不应该进行那么多的集成测试。重点应放在单元测试上,这在应用依赖注入模式时应该很容易。最重要的是,与依赖于非常宽的库定义的接口相比,有更好的方法可以将容器从集成测试中隐藏起来。
自己定义这样的接口(加上一个适配器)是微不足道的,这证明没有它在库中。作为应用程序开发人员,您可以按照Dependency Inversion Principle的规定为应用程序定义正确的抽象。倾向于这样做的图书馆和框架在提供适合每个人的抽象时大多数时间都会失败。
根据Framework Design Guidelines,库本身不使用那个抽象,而库应该没有为你定义这样的抽象。正如前面所述,Simple Injector无论如何都会使抽象错误。
最后但并非最不重要的是,Simple Injector容器确实实现了System.IServiceProvider,它在mscorlib.dll中定义,可用于检索服务对象。
答案 1 :(得分:0)
我认为这里给出的答案完全建立在接受ServiceLocator是一种反模式的基础上,反过来我不相信全球公认的是真实的。请参阅Windows Workflow Foundation的扩展支持。
反模式链接(及其两个更新)也可能很弱...最新的更新声称违反了封装("减轻了你必须理解每一段代码的每个实现细节的负担在你的代码库中。")然后同时声称依赖关系的前期知识在某种程度上与通过单元测试发现它们不同。无论哪种方式,你都需要知道要给它什么。
总而言之,如果你想要遵循定位器模式,可以利用它的IServiceProvider,或者简化你的容器数量(到单例)并为它创建一个静态包装器。