作为“模拟者”TDD从业者,我应该在与被测试方法相同的类中模拟其他方法吗?

时间:2008-10-08 20:25:12

标签: tdd mocking

在阅读了Martin Fowler的Mocks Aren't Stubs之后,我发现我一直在以“模仿者”的方式练习TDD。

但是我想知道即使是在模仿者TDD,如果一个人可以嘲笑太远。

这是Python风格的伪代码中的更新示例:

def sync_path(self):
    if self.confirm_or_create_connection():
        self.sync(self.dirpath)

confirm_or_create_connection()方法创建与服务器的连接。

我在两个测试中测试了一个类似于此的方法,两个测试都模拟confirm_or_create_connection()和sync()(即使它们都是同一个类中的方法)。在一个测试中,模拟confirm_or_create_connection()返回True,测试确认调用了sync(),另一个模拟confirm_or_create_connection()返回False,测试确认未调用sync()。

这合理吗?或者我应该模拟confirm_or_create_connection()和sync()调用的对象? (我已经对这两种方法进行了其他测试。)

请不要通过解释我应该练习“经典”TDD来回答这个问题。这是另一个问题的答案:Should I practice mockist or classical TDD?

7 个答案:

答案 0 :(得分:8)

该技术被称为“模拟对象”,而不是“模拟方法”。它鼓励将系统划分为易于组合的协作对象而远离程序代码的设计。目的是提高抽象级别,以便您通常通过编写对象进行编程,并且很少编写低级控制流语句。

答案 1 :(得分:5)

我个人认为嘲笑自我几乎总是代码味道。它正在测试实现而不是行为。

答案 2 :(得分:4)

编辑更新样本:

我现在看到了。您在测试此类时遇到问题,因为它存在设计缺陷。本课程违反了单一责任原则。它做了两件事。首先,它正在管理与数据库的连接。它也正在同步。

您需要一个单独的类来管理数据库连接。该类将是被测试类的依赖项。当你对被测试的类进行单元测试时,数据库连接类可以伪造。

原名:

  

作为同事互动测试员,   如果你有一个,请考虑重构   需要这样做。那课是   可能做得太多了。

     

让我这样对待你:打电话   私有方法不会成为   相互作用。

     

这是TDD的要点之一。   当它伤害你的设计时可以   改善。

答案 3 :(得分:1)

为新示例编辑
对我而言,你看起来像是在断开confirm_or_create_connection,你只对定义返回调用感兴趣并且你在模拟同步,在这里你有兴趣测试它是否真的被调用。 (我必须检查我的存根或嘲弄的定义是否与您引用的捕鸟文章相同。自从我阅读它以来我已经有一段时间了,我一直在使用c#中的rhinomocks,它可能有它自己的定义这些术语:-))

我认为你正在测试嘲笑和抄袭这些电话是正确的方法。如果其中一个函数出现错误,您不希望测试失败,还有其他测试。您只想测试sync_path的操作。

我同意Avdi的说法,这有点臭。测试还可以,但是你的课程可能做得太多了。

答案 4 :(得分:1)

疯狂地猜测,看起来连接活动可能属于另一个应委托给它的对象,在这种情况下你可以模拟那个。我通常建议不要嘲笑对象的一部分来测试另一部分。它表明有两个概念用螺栓连接在一起。

答案 5 :(得分:0)

你能嘲笑太远吗?我不知道太过分了,但它可以做得很糟糕,以至于你实际上是在测试模拟而不是代码,或者更糟糕的是你要进行脆弱的测试。

但只要你正在编写好的测试 - 确认你预期行为的测试,帮助你编写代码的测试 - 然后模拟!

答案 6 :(得分:0)

以下是一篇很好的解读:“原则:不要在http://xunitpatterns.com/Principles%20of%20Test%20Automation.html#Don修改SUT”

通过模拟或删除部分实现来修改您正在测试的类是一种代码味道。远离它的重构是将你正在嘲笑/捣乱的部分移动到另一个类。这说它并不总是一件可怕的事情。它的代码味道,但并不总是不合适。对于像C#或Java这样的语言,你有很好的重构工具,很容易修复这个代码的味道,我通常会(在C#中,假设Java类似)。我在Lua和Javascript中做了很多开发,但事情有点不同。使用这些语言创建和管理大量类更加困难,因此我更容忍在测试中修改SUT。一旦最初的测试覆盖范围存在,我总能解决这个问题。它需要额外的照顾。