【问题标题】:Mocking an IoC Container?模拟 IoC 容器?
【发布时间】:2011-04-22 23:59:52
【问题描述】:

模拟 IoC 容器有意义吗?如果是这样,我将如何使用 Moq?

我正在创建一个 Prism 4 应用,使用 Unity 2.0 作为 IoC 容器。我将容器注入到需要其服务的类中,而不是使用 Prism 的ServiceLocator。对于单元测试,除非我的测试需要其他 Prism 服务,否则我只需实例化容器并使用它注册模拟。我将容器传递给正在测试的类,它会解析模拟。

这一切都相当简单,但我想知道是否应该模拟容器?为什么?如果是这样,如果我使用 Moq 作为我的模拟框架,我会怎么做?感谢您的帮助。

【问题讨论】:

    标签: unit-testing mocking prism moq


    【解决方案1】:

    不,模拟 DI 容器没有意义,因为 application classes should not reference a container at all

    不要将容器注入到类中,而应该只注入它们需要的服务。这也意味着您可以unit test them without referencing a DI container at all

    【讨论】:

    • 您是否厌倦了一遍又一遍地回答同一个问题?
    • 谢谢,马克。这些参考资料将帮助我掌握这个领域。如果你厌倦了反复回答这些问题,那么你就是在为像我这样正在攀登学习曲线的人提供宝贵的帮助。不胜感激。
    • Mark 出版了一本名为“.NET 中的依赖注入”的书,看起来相当不错。纸质版将于 7 月到期,电子书现已推出:manning.com/seemann
    • 我翻阅了 Mark 的书——非常好。它清除了我已经挣扎了一段时间的 DI 的许多令人费解的方面。非常值得,我对马克的回答有了更好的理解。对于其他研究这个问题的人来说——这是非常基础的。非常值得花几天时间来解决这个问题。我在研究问题时所获得的理解(大部分是使用 Mark 的书)将导致我设计应用程序的方式发生重大变化——变得更好。
    【解决方案2】:

    对于 99% 的课程,我同意 Mark Seemann 的回答,这很好用。

    有一些工厂类型的类(可能是接受模型并将其转换为 ViewModel 的类,这些 ViewModel 具有依赖项)对此不起作用。在这些情况下,我通常接受容器的接口,而不是它的具体类型(在您的情况下为 IUnityContainer)并像往常一样模拟。

    public class MyWidgetFactory : IMyWidgetFactory
    {
         public MyWidgetFactory(IUnityContainer container)
         {
              //...
         }
         public Widget[] GetWidgets()
         {
             //...
         }
    }
    
    public class MyWidgetFactoryConsumer
    {
         private Widget[] _widgets;
         public MyWidgetFactoryConsumer(IMyWidgetFactory factory)
         {
              _widgets = factory.GetWidgets();
         }
    }
    

    上述两个类都是可测试的,工厂类需要具有 IUnityContainer 的模拟版本,而消费者只需要模拟工厂本身。

    【讨论】:

    • 你不需要这样做。在 Unity 中,使用 deferred resolution(自动工厂)。
    • 不需要这样做。一般的解决方案是使用抽象工厂:stackoverflow.com/questions/1943576/… 一些容器开箱即用地支持这一点。 Castle Windsor 拥有 Typed Factory 设施。
    • @TrueWill:这是一个非常棒的功能。我将回复 Mark Seemann 提出一个一直困扰我的问题。看看你有没有想法。
    • @Mark Seemann:我们经常遇到这样的情况,我们需要收集模型对象并将它们转换为 ViewModel。这些视图模型具有应用程序依赖项,但它们也需要传递模型对象或模型对象的属性才能正确构造。因此,除了传递应用程序依赖项之外,我们还需要传递用于构造的参数(我们为此使用 Unity 的 ParameterOverride 功能),而不是像您链接到的抽象工厂示例那样传递简单的参数。在这些情况下你会怎么做?
    • @Mark Seemann:我应该说,显然工厂可以拥有依赖项,然后将对这些依赖项的引用传递给每个构造的对象,但是依赖注入的好处之一是更改构造函数签名更多依赖项不需要修复其他代码。我承认这是一个合乎逻辑的选择,但我希望可能有更多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-29
    • 2011-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-09
    相关资源
    最近更新 更多