我读过各种关于测试中模仿和存根的文章,包括Martin Fowler的《Mocks Aren't Stubs》,但我仍然不理解其中的区别。
当前回答
Stub是实现组件接口的对象,但是Stub可以配置为返回适合测试的值,而不是返回调用时组件将返回的值。使用存根,单元测试可以测试一个单元是否可以处理来自合作者的各种返回值。在单元测试中使用存根而不是真正的合作者可以这样表示:
单元测试——>存根
单元测试——>单元——>存根
单元测试对结果和单元状态进行断言
首先,单元测试创建存根并配置其返回值。然后单元测试创建单元并在其上设置存根。现在,单元测试调用单元,而单元又调用存根。最后,单元测试对单元上的方法调用的结果进行断言。
A Mock is like a stub, only it also has methods that make it possible determine what methods where called on the Mock. Using a mock it is thus possible to both test if the unit can handle various return values correctly, and also if the unit uses the collaborator correctly. For instance, you cannot see by the value returned from a dao object whether the data was read from the database using a Statement or a PreparedStatement. Nor can you see if the connection.close() method was called before returning the value. This is possible with mocks. In other words, mocks makes it possible to test a units complete interaction with a collaborator. Not just the collaborator methods that return values used by the unit. Using a mock in a unit test could be expressed like this:
单元测试——>模拟
单元测试—>单元—>模拟
单元测试对单元的结果和状态进行断言
单元测试断言在mock上调用的方法
>>这里
其他回答
我在阅读《单元测试的艺术》时,偶然发现了以下定义:
fake是一个通用术语,可以用来描述存根或模拟对象(手写或其他),因为它们看起来都像真实的对象。赝品是存根还是mock取决于它在当前测试中的使用方式。如果它用于检查交互(根据其断言),则它是一个模拟对象。否则,它就是存根。
在我的回答中,我使用了python示例来说明差异。
Stub - Stubbing is a software development technique used to implement methods of classes early in the development life-cycle. They are used commonly as placeholders for implementation of a known interface, where the interface is finalized or known but the implementation is not yet known or finalized. You begin with stubs, which simply means that you only write the definition of a function down and leave the actual code for later. The advantage is that you won't forget methods and you can continue to think about your design while seeing it in code. You can also have your stub return a static response so that the response can be used by other parts of your code immediately. Stub objects provide a valid response, but it's static no matter what input you pass in, you'll always get the same response:
class Foo(object):
def bar1(self):
pass
def bar2(self):
#or ...
raise NotImplementedError
def bar3(self):
#or return dummy data
return "Dummy Data"
模拟对象用于模拟测试用例,它们验证在这些对象上调用了某些方法。模拟对象是以可控的方式模拟真实对象行为的模拟对象。您通常创建一个模拟对象来测试其他对象的行为。mock让我们模拟对于单元测试来说不可用或太笨重的资源。
mymodule.py:
import os
import os.path
def rm(filename):
if os.path.isfile(filename):
os.remove(filename)
test.py:
from mymodule import rm
import mock
import unittest
class RmTestCase(unittest.TestCase):
@mock.patch('mymodule.os')
def test_rm(self, mock_os):
rm("any path")
# test that rm called os.remove with the right parameters
mock_os.remove.assert_called_with("any path")
if __name__ == '__main__':
unittest.main()
这是一个非常基本的示例,它只运行rm并断言调用它的参数。您可以对对象使用mock,而不仅仅是这里所示的函数,您还可以返回一个值,这样模拟对象就可以用来替换存根进行测试。
更多关于unittest的信息。模拟,注意python 2。X mock不包含在unittest中,但它是一个可下载的模块,可以通过PIP (PIP install mock)下载。
我还读过Roy Osherove写的《单元测试的艺术》,我认为如果有一本类似的书是用Python和Python示例编写的,那就太棒了。如果有人知道这样的书,请分享。欢呼:)
从论文模拟角色,而不是对象,由jMock的开发人员:
存根是返回罐装的产品代码的虚拟实现 结果。Mock对象充当存根,但也包括到的断言 测量目标对象与其邻居的交互作用。
所以,主要的区别是:
在存根上设置的期望通常是通用的,而在mock上设置的期望可能更“聪明”(例如,在第一次调用时返回this,在第二次调用时返回this等)。 存根主要用于设置SUT的间接输入,而mock可用于测试SUT的间接输入和间接输出。
综上所述,同时也试图驱散福勒文章标题中的困惑:mock是存根,但它们不仅仅是存根。
下面是对每一个的描述,然后是真实世界的样本。
Dummy - just bogus values to satisfy the API. Example: If you're testing a method of a class which requires many mandatory parameters in a constructor which have no effect on your test, then you may create dummy objects for the purpose of creating new instances of a class. Fake - create a test implementation of a class which may have a dependency on some external infrastructure. (It's good practice that your unit test does NOT actually interact with external infrastructure.) Example: Create fake implementation for accessing a database, replace it with in-memory collection. Stub - override methods to return hard-coded values, also referred to as state-based. Example: Your test class depends on a method Calculate() taking 5 minutes to complete. Rather than wait for 5 minutes you can replace its real implementation with stub that returns hard-coded values; taking only a small fraction of the time. Mock - very similar to Stub but interaction-based rather than state-based. This means you don't expect from Mock to return some value, but to assume that specific order of method calls are made. Example: You're testing a user registration class. After calling Save, it should call SendConfirmationEmail.
存根和Mock实际上是Mock的子类型,两者都交换了实际实现和测试实现,但出于不同的、特定的原因。
存根是一个简单的伪对象。它只是确保测试顺利进行。 mock是更聪明的存根。您验证您的测试通过了它。
推荐文章
- 如何模拟低带宽、高延迟的环境?
- 使用Moq验证方法调用
- 我如何“休眠”Dart程序
- 使用Mockito的泛型“any()”方法
- Mockito中检测到未完成的存根
- 尝试模拟datetime.date.today(),但不工作
- 如何用python timeit对代码段进行性能测试?
- 确定bash中是否存在一个函数
- 如何使用“测试”包打印Go测试?
- 如何在IntelliJ中为整个项目配置“缩短命令行”方法
- toBe(true) vs toBeTruthy() vs toBeTrue()
- 使用Mockito测试抽象类
- 什么时候应该使用Debug.Assert()?
- 使用Moq模拟扩展方法
- 从控制台停止一个Android应用程序