'SentinelObject'对象没有属性'reset_mock'

时间:2011-11-22 09:35:18

标签: python unit-testing mocking

我不确定为什么以下代码无效。我正在使用Mock framework。有人可以向我解释一下吗?

我得到的错误是:

$ 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 个答案:

答案 0 :(得分:3)

问题(遗憾地)是微不足道的。我正在修补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 ??? ...