在阅读了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?
答案 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。一旦最初的测试覆盖范围存在,我总能解决这个问题。它需要额外的照顾。