SentinelObject'对象没有'reset_mock'属性
我不太明白为什么下面的代码不管用。我正在使用Mock框架。有人能给我解释一下吗?
我遇到的错误是:
$ python test_mock.py
Calls the mock object method. not a real one. ... ERROR
======================================================================
ERROR: Calls the mock object method. not a real one.
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_mock.py", line 37, in test_is_method_called
self.sut.do_something()
File "test_mock.py", line 21, in do_something
self.__obj.method()
File "build/bdist.linux-i686/egg/mock.py", line 365, in __getattr__
self._children[name] = self._get_child_mock(parent=self, name=name, wraps=wraps)
File "build/bdist.linux-i686/egg/mock.py", line 458, in _get_child_mock
return klass(**kw)
File "build/bdist.linux-i686/egg/mock.py", line 282, in __init__
self.reset_mock()
File "build/bdist.linux-i686/egg/mock.py", line 303, in reset_mock
self._return_value.reset_mock()
AttributeError: 'SentinelObject' object has no attribute 'reset_mock'
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (errors=1)
代码是:
import unittest
import mock
class Fubar ():
def __init__(self):
pass
def method (self):
print "I am a Stup!d Monkey!"
class Monkey ():
def __init__(self, obj):
self.__obj = obj
def do_something (self):
if not isinstance(self.__obj, Fubar):
raise RuntimeError
self.__obj.method()
class TestMoneky (unittest.TestCase):
def setUp(self):
self.mock_obj = mock.Mock(name="Mock object", spec=["method"])
self.sut = Monkey(self.mock_obj)
def tearDown(self):
pass
def test_is_method_called (self):
"""Calls the mock object method. not a real one."""
with mock.patch("__builtin__.isinstance") as mock_inst:
mock_inst.return_value = True
self.sut.do_something()
self.assertTrue(self.mock_obj.method.called)
def main ():
"""Simple runner."""
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestMoneky))
unittest.TextTestRunner(verbosity=2).run(suite)
if __name__ == '__main__':
main()
1 个回答
4
问题其实很简单。我的做法是把 isinstance()
这个函数改成总是返回 True。所以在模块的某个地方,有东西在检查我的模拟对象是不是一个 Sentinel(哨兵对象),因为我改了返回值,所以它返回了 True。这就导致了内部行为不对劲。
解决办法就是不要改 isinstance()
,而是给模拟对象提供一个和它应该匹配的类相符的规格:
def setUp(self):
self.mock_obj = mock.Mock(name="Mock object", spec=Fubar)
self.sut = Monkey(self.mock_obj)
def test_is_method_called (self):
"""Calls the mock object method. not a real one."""
self.sut.do_something()
self.assertTrue(self.mock_obj.method.called)
有没有人能想到一种方法来做到这一点,而不把模拟对象和 Fubar
绑定在一起???...