调用从“spec”创建的模拟的模拟方法的不存在方法时引发错误
Raise error when calling a non-existent method of a mocked method of a mock created from `spec`
from unittest import mock
class A:
def f(self): pass
m = mock.MagicMock(spec_set=A)
m.f.called_once() # I want this to fail
Out[42]: <MagicMock name='mock.f.called_once()' id='140326790593792'>
我在单元测试中犯了一个错误,在模拟方法上调用了 called_once
而不是 assert_called_once
。调用会产生一个新的 MagicMock
实例,因此测试通过了,但没有检查我打算检查的内容——如果调用了该方法。当从 spec_set
创建 mock 时,如果未定义方法,是否有办法使 mock 失败?就像我希望 spec_set
一直应用到方法模拟本身。
使用create_autospec
:
from unittest import mock
class A:
def f(self): pass
m = mock.create_autospec(A)
m.f()
m.f.assert_called_once() # works OK
m.f.misstyped_called_once() # raises
Traceback (most recent call last):
File "/Users/ant/opt/miniconda3/envs/deeplearning/lib/python3.8/site-packages/IPython/core/interactiveshell.py", line 3437, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-85-8fe8ab09b722>", line 7, in <module>
m.f.misstyped_called_once() # raises
File "/Users/ant/opt/miniconda3/envs/deeplearning/lib/python3.8/unittest/mock.py", line 637, in __getattr__
raise AttributeError("Mock object has no attribute %r" % name)
AttributeError: Mock object has no attribute 'misstyped_called_once'
原来文档中有一整节专门讨论这个主题:https://docs.python.org/3/library/unittest.mock.html#autospeccing
Autospeccing is based on the existing spec feature of mock. It limits the api of mocks to the api of an original object (the spec), but it is recursive (implemented lazily) so that attributes of mocks only have the same api as the attributes of the spec.
编辑
看起来有一个 school of thought 避免使用 assert_called_xxx
支持显式
assert mock_restart.call_count == 1
assert mock_restart.call_args == mock.call(“some argument”)
和 another school 提出了一种方法论解决方案——如果你做 TDD,那么你的测试 必须 在你投入任何实现之前失败,这可以防止错误正面。
from unittest import mock
class A:
def f(self): pass
m = mock.MagicMock(spec_set=A)
m.f.called_once() # I want this to fail
Out[42]: <MagicMock name='mock.f.called_once()' id='140326790593792'>
我在单元测试中犯了一个错误,在模拟方法上调用了 called_once
而不是 assert_called_once
。调用会产生一个新的 MagicMock
实例,因此测试通过了,但没有检查我打算检查的内容——如果调用了该方法。当从 spec_set
创建 mock 时,如果未定义方法,是否有办法使 mock 失败?就像我希望 spec_set
一直应用到方法模拟本身。
使用create_autospec
:
from unittest import mock
class A:
def f(self): pass
m = mock.create_autospec(A)
m.f()
m.f.assert_called_once() # works OK
m.f.misstyped_called_once() # raises
Traceback (most recent call last):
File "/Users/ant/opt/miniconda3/envs/deeplearning/lib/python3.8/site-packages/IPython/core/interactiveshell.py", line 3437, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-85-8fe8ab09b722>", line 7, in <module>
m.f.misstyped_called_once() # raises
File "/Users/ant/opt/miniconda3/envs/deeplearning/lib/python3.8/unittest/mock.py", line 637, in __getattr__
raise AttributeError("Mock object has no attribute %r" % name)
AttributeError: Mock object has no attribute 'misstyped_called_once'
原来文档中有一整节专门讨论这个主题:https://docs.python.org/3/library/unittest.mock.html#autospeccing
Autospeccing is based on the existing spec feature of mock. It limits the api of mocks to the api of an original object (the spec), but it is recursive (implemented lazily) so that attributes of mocks only have the same api as the attributes of the spec.
编辑
看起来有一个 school of thought 避免使用 assert_called_xxx
支持显式
assert mock_restart.call_count == 1
assert mock_restart.call_args == mock.call(“some argument”)
和 another school 提出了一种方法论解决方案——如果你做 TDD,那么你的测试 必须 在你投入任何实现之前失败,这可以防止错误正面。