diff options
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | mocker.py | 30 | ||||
-rwxr-xr-x | test.py | 27 |
3 files changed, 51 insertions, 10 deletions
@@ -6,6 +6,10 @@ environments which inspect the result's type, such as in iPython (reported by Alex Dante). +- Now Mocker.mock()/proxy()/replace() accept a 'count' keyword + parameter, which if set to False, the default behavior of allowing + expressions just once is disabled. + 0.9.1 (2007-11-18) ================== @@ -463,7 +463,8 @@ class MockerBase(object): message.append("") raise AssertionError(os.linesep.join(message)) - def mock(self, spec_and_type=None, spec=None, type=None, name=None): + def mock(self, spec_and_type=None, spec=None, type=None, + name=None, count=True): """Return a new mock object. @param spec_and_type: Handy positional argument which sets both @@ -476,12 +477,17 @@ class MockerBase(object): @param name: Name for the mock object, used in the representation of expressions. The name is rarely needed, as it's usually guessed correctly from the variable name used. + @param count: If set to false, expressions may be executed any number + of times, unless an expectation is explicitly set using + the L{count()} method. By default, expressions are + expected once. """ if spec_and_type is not None: spec = type = spec_and_type - return Mock(self, spec=spec, type=type, name=name) + return Mock(self, spec=spec, type=type, name=name, count=count) - def proxy(self, object, spec=True, type=True, name=None, passthrough=True): + def proxy(self, object, spec=True, type=True, name=None, count=True, + passthrough=True): """Return a new mock object which proxies to the given object. Proxies are useful when only part of the behavior of an object @@ -508,6 +514,10 @@ class MockerBase(object): @param name: Name for the mock object, used in the representation of expressions. The name is rarely needed, as it's usually guessed correctly from the variable name used. + @param count: If set to false, expressions may be executed any number + of times, unless an expectation is explicitly set using + the L{count()} method. By default, expressions are + expected once. @param passthrough: If set to False, passthrough of actions on the proxy to the real object will only happen when explicitly requested via the L{passthrough()} @@ -536,9 +546,9 @@ class MockerBase(object): if type is True: type = __builtin__.type(object) return Mock(self, spec=spec, type=type, object=object, - name=name, passthrough=passthrough) + name=name, count=count, passthrough=passthrough) - def replace(self, object, spec=True, type=True, name=None, + def replace(self, object, spec=True, type=True, name=None, count=True, passthrough=True): """Create a proxy, and replace the original object with the mock. @@ -570,7 +580,7 @@ class MockerBase(object): explicitly requested via the L{passthrough()} method. """ - mock = self.proxy(object, spec, type, name, passthrough) + mock = self.proxy(object, spec, type, name, count, passthrough) event = self._get_replay_restore_event() event.add_task(ProxyReplacer(mock)) return mock @@ -944,7 +954,7 @@ recorder = Mocker.add_recorder class Mock(object): def __init__(self, mocker, path=None, name=None, spec=None, type=None, - object=None, passthrough=False, patcher=None): + object=None, passthrough=False, patcher=None, count=True): self.__mocker__ = mocker self.__mocker_path__ = path or Path(self, object) self.__mocker_name__ = name @@ -954,6 +964,7 @@ class Mock(object): self.__mocker_patcher__ = patcher self.__mocker_replace__ = False self.__mocker_type__ = type + self.__mocker_count__ = count def __mocker_act__(self, kind, args=(), kwargs={}, object=None): if self.__mocker_name__ is None: @@ -1600,8 +1611,9 @@ class ImplicitRunCounter(RunCounter): @recorder def run_counter_recorder(mocker, event): - """In principle, any event may be repeated once.""" - event.add_task(ImplicitRunCounter(1)) + """Any event may be repeated once, unless disabled by default.""" + if event.path.root_mock.__mocker_count__: + event.add_task(ImplicitRunCounter(1)) @recorder def run_counter_removal_recorder(mocker, event): @@ -977,6 +977,13 @@ class MockerTest(unittest.TestCase): MyMocker.remove_recorder(obj1) self.assertEquals(MyMocker.get_recorders(), [obj2]) + def test_mock(self): + mock = self.mocker.mock() + self.assertEquals(mock.__mocker_name__, None) + self.assertEquals(mock.__mocker_spec__, None) + self.assertEquals(mock.__mocker_type__, None) + self.assertEquals(mock.__mocker_count__, True) + def test_mock_with_name(self): mock = self.mocker.mock(name="name") self.assertEquals(mock.__mocker_name__, "name") @@ -997,12 +1004,23 @@ class MockerTest(unittest.TestCase): self.assertEquals(mock.__mocker_spec__, C) self.assertEquals(mock.__mocker_type__, C) + def test_mock_with_count(self): + class C(object): pass + mock = self.mocker.mock(count=False) + self.assertEquals(mock.__mocker_count__, False) + def test_proxy(self): original = object() mock = self.mocker.proxy(original) self.assertEquals(type(mock), Mock) self.assertEquals(mock.__mocker_object__, original) self.assertEquals(mock.__mocker_path__.root_object, original) + self.assertEquals(mock.__mocker_count__, True) + + def test_proxy_with_count(self): + original = object() + mock = self.mocker.proxy(original, count=False) + self.assertEquals(mock.__mocker_count__, False) def test_proxy_with_spec(self): original = object() @@ -1063,13 +1081,14 @@ class MockerTest(unittest.TestCase): def test_replace(self): from os import path obj = object() - proxy = self.mocker.replace(obj, spec=object, name="obj", + proxy = self.mocker.replace(obj, spec=object, name="obj", count=False, passthrough=False) self.assertEquals(type(proxy), Mock) self.assertEquals(type(proxy.__mocker_object__), object) self.assertEquals(proxy.__mocker_object__, obj) self.assertEquals(proxy.__mocker_spec__, object) self.assertEquals(proxy.__mocker_name__, "obj") + self.assertEquals(proxy.__mocker_count__, False) (event,) = self.mocker.get_events() self.assertEquals(type(event), ReplayRestoreEvent) (task,) = event.get_tasks() @@ -2065,6 +2084,7 @@ class MockTest(unittest.TestCase): self.assertEquals(self.mock.__mocker_passthrough__, False) self.assertEquals(self.mock.__mocker_patcher__, None) self.assertEquals(self.mock.__mocker_replace__, False) + self.assertEquals(self.mock.__mocker_count__, True) def test_path(self): path = object() @@ -2675,6 +2695,11 @@ class RunCounterTest(unittest.TestCase): self.assertTrue(task.min == 1) self.assertTrue(task.max == 1) + def test_recorder_wont_record_when_count_is_false(self): + self.mock.__mocker_count__ = False + run_counter_recorder(self.mocker, self.event) + self.assertEquals(self.event.get_tasks(), []) + def test_removal_recorder(self): """ Events created by getattr actions which lead to other events |