我应该在单元测试时模拟所有依赖项吗?

Fab*_*iro 8 unit-testing mocking

我的班级有依赖,我在单元测试中嘲笑.我在一个对我没有多大意义的地方得到了一个空引用异常.

我刚才意识到这是因为我没有设置我的模拟依赖.此依赖项已经过测试,但它不会连接到文件系统或数据源之类的任何内容.

我只想在这个新类中测试我的新代码,但我想在这种情况下最好不要去模拟.

这个结论是否正确?

Dav*_*uth 8

这听起来像是在你的情况下工作,但一般情况下,存根或模拟的唯一原因是获取外部数据源,而不是测试的头发.其他原因包括

  • 一个方法本身可能很慢
  • 可能很难找到合适的参数来传递给另一个类的方法,让它返回你测试方法所需的值
  • 您正在测试的方法需要另一个更改了很多的类的实例,并且当被调用者更改时您不希望调用者的测试中断
  • 您依赖的方法很复杂,需要自己的测试,完全测试您的方法而不用存根或模拟意味着完全测试它调用的方法(在您方法自己的测试中),这会导致类和测试的测试之间的重复它调用的方法
  • 你是从外面做TDD而你还没有写过被调用者,只是设计了它的界面!


Ida*_*rye 6

正确.你应该模仿依赖于持久性或外部性的东西,以防止测试依赖于持久性或外部性.

如果依赖关系不依赖于任何持久性或外部性,那么通过模拟它获得的唯一好处是即使依赖性错误,测试也能正常工作 - 但假设模拟正常工作.为此你需要:

  1. 编写一个完全模拟依赖关系的模拟.

  2. 编写一个模拟,模拟将在测试中使用的特定情况的依赖关系.

第一种选择是彻头彻尾的荒谬 - 为什么你的模拟比原来的依赖更好?毕竟,可以安全地假设在原始依赖中投入了比在模拟中更多的努力......

第二个选项意味着您的mock知道实现的确切细节 - 否则您将不知道实现如何使用依赖项,因此您不知道如何模拟这些特定用途.这意味着测试不能满足单元测试的主要目的之一 - 在更改实现后验证代码是否正常工作.

模拟的缺点太大而且优点太小 - 特别是考虑到你总是可以运行依赖项的测试来检查它是否正常工作......

  • 我恭敬地不同意。我认为对此有一个更好的答案:/sf/ask/2672701/ (4认同)
  • “持久”意味着它在测试之前就已经存在,并且在测试之后将保留在那里——在测试期间对它所做的所有更改都保留下来。这可能是一个问题,因为您需要在测试前确保它的状态是正确的,并且需要在测试后将其保持在稳定状态(对于其他想要使用它的东西)“外部”意味着它会影响外部的事物测试 - 您通常不想影响的事情。 (3认同)