【问题标题】:Pass an interface object to constructor or method将接口对象传递给构造函数或方法
【发布时间】:2012-07-19 09:08:44
【问题描述】:

我正在编写一个测试,我必须将一个模拟传递给一个特定的方法。我想知道,通过构造函数或直接将它传递给相关方法有什么好处。还是真的不重要。

例如

通过构造函数传递接口/模拟

class User()
{
  IClock clock;

  User(IClock clock) {this.clock = clock;}

  User GetUser(){ ..}
  UpdateUser(User user) {
     ... 
     this.clock.Now();
     ...
  }
}

将接口/模拟传递给方法

class User()
{
  User GetUser(){ ..}
  UpdateUser(IClock clock, User user) {
     ... 
     clock.Now();
     ...
  }
}

谢谢!

编辑

在这种情况下,IClock 将包装 DateTime。我这样做是为了可测试性。如此有效,我将有一个覆盖,将在其内部构造 IClock。

EG。对于方法案例:

UpdateUser(User user) {
  UpdateUser(new Clock(), user);
}

时钟将封装日期时间。

【问题讨论】:

    标签: oop testing mocking


    【解决方案1】:

    在这种情况下,IClock 是一个隐藏的单例 - 它从底层操作系统生成当前日期时间。如果您想编写可靠的验收测试,则需要在这些测试中删除日期时间提供程序。

    因此,您需要将这种依赖关系一直暴露到模块边界,然后将公共日期时间源注入您的模块(甚至可能是整个系统)。在编写验收测试时,您有时会存根此“IClock”日期时间源。

    这将允许您回答以下问题:

    • 我的系统在闰日工作吗?
    • 我的系统在午夜工作吗?
    • 我的系统在除夕夜能正常工作吗?

    在构造函数签名或方法签名中具有 IClock 依赖项将清楚地向用户说明您的方法或对象是日期时间相关的。在试图理解对象的行为时,对日期时间的依赖通常至关重要,因此应予以重视。通常避免任何隐藏这种依赖关系的东西(例如在重载的方法定义中提供默认的日期时间源),因为这会阻止你编写像我上面描述的那样的验收测试。

    在将依赖项传递给构造函数还是方法之间进行选择通常取决于方法对系统其余部分的责任。这些方法构成了对象将用于与运行系统中的对等方通信的公共协议,而构造函数参数是此特定实现执行其角色所需的依赖项。

    问自己这些问题:

    • 此方法的职责是否一定需要了解日期时间?
    • 或者它是否与此特定对象中方法的特定实现有关,这意味着它需要日期时间?
    • 由方法的调用者负责操作此对象的日期时间视图是否合理,还是由模块配置负责?
    • 如果我将此对象与同一接口的另一个实现交换,那么该实现不需要此方法的日期时间是否合理?
    • 您的对象中有多少方法需要日期时间?他们需要相同的日期时间视图吗?

    【讨论】:

      【解决方案2】:

      这取决于谁知道IClock:在构造User 的地方可用还是在调用UpdateUser 的地方可用?

      如果将它传递给构造函数,则可以传递User 对象,任何人都可以调用UpdateUser,但如果你通过UpdateUser 传递它,任何使用该方法的人都必须持有IClock参考。

      【讨论】:

      • 其实在这种情况下,IClock 会包装 DateTime。我已经编辑了帖子以反映这一点。
      • @Newton:在这种情况下,我宁愿把它放在构造函数中,因为它减少了类中公共方法的数量。
      • @casablanca 我认为你提出了一个非常好的观点“如果你通过 UpdateUser 传递它,任何使用该方法的人都必须持有 IClock 引用”。
      【解决方案3】:

      将依赖项(即IClock)传递给构造函数,即构造函数注入通常意味着这是给定类的整个对象的必需的依赖项。将依赖传递给类的方法,即 方法注入 只使这个特定的方法依赖它。还有其他两种可能性:向属性注入依赖项(属性注入,即类对象的可选依赖项)和很少使用的环境上下文。

      所以这更多的是你团队中代码风格的品味、设计和一致性问题。

      在您的示例中,User 的对象不需要依赖 IClock,因此方法注入更合适。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-07-15
        • 2014-06-04
        • 1970-01-01
        • 1970-01-01
        • 2011-08-31
        • 2012-07-09
        • 1970-01-01
        • 2011-10-24
        相关资源
        最近更新 更多