我对模拟和虚假对象有基本的了解,但我不确定我对使用模拟的时间/地点有所了解 - 特别是因为它适用于这种情况here。
答案 0 :(得分:141)
答案 1 :(得分:109)
单元测试应该通过单个方法测试单个代码路径。当方法的执行从该方法之外传递到另一个对象,然后再返回时,您就有了依赖关系。
当您使用实际依赖项测试该代码路径时,您不是单元测试;你是集成测试。虽然这是好的和必要的,但它不是单元测试。
如果您的依赖项存在问题,则您的测试可能会以某种方式受到影响,从而导致误报。例如,您可以将依赖项传递给意外的null,并且依赖项可能不会因为文档记录而抛出null。你的测试没有发现它应该有的null参数异常,并且测试通过了。
此外,您可能会发现很难(如果不是不可能的话)可靠地让依赖对象在测试期间准确地返回您想要的内容。这还包括在测试中抛出预期的异常。
模拟取代了该依赖项。您可以设置对依赖对象的调用的期望,设置它应该为您执行所需的测试提供的确切返回值,和/或要抛出的异常,以便您可以测试异常处理代码。通过这种方式,您可以轻松地测试相关单元。
TL; DR:嘲笑你的单元测试所涉及的每一个依赖。
答案 2 :(得分:46)
经验法则:
如果您正在测试的函数需要一个复杂的对象作为参数,并且简单地实例化此对象(例如,如果它尝试建立TCP连接)将是一件痛苦的事情,请使用模拟。
答案 3 :(得分:3)
当您在尝试测试的代码单元中具有依赖关系时,您应该模拟对象,这需要“只是这样”。
例如,当您尝试在代码单元中测试某些逻辑但是您需要从另一个对象获取某些内容时,从该依赖项返回的内容可能会影响您尝试测试的内容 - 模拟该对象。
可以找到关于该主题的精彩播客here