-
-
Save pelme/59a1dee00b5f8afc278e to your computer and use it in GitHub Desktop.
stub fixture - use at your own risk
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from mock import patch, DEFAULT | |
def is_exception(thing): | |
try: | |
return isinstance(thing, BaseException) or issubclass(thing, BaseException) | |
except TypeError: | |
return False | |
def _patch_method(obj, method_name, return_value=DEFAULT, **kwargs): | |
if is_exception(return_value): | |
kwargs['side_effect'] = return_value | |
else: | |
kwargs['return_value'] = return_value | |
kwargs['autospec'] = True | |
# Allow specifying a dotted string instead of an object | |
if isinstance(obj, basestring): | |
return patch('%s.%s' % (obj, method_name), **kwargs) | |
assert callable(getattr(obj, method_name)), 'Tried to mock %s.%s which is not callable!' % (obj, method_name) | |
return patch.object(obj, method_name, **kwargs) | |
class Mocks(object): | |
def __init__(self, data): | |
self.__dict__.update(data) | |
class Stub(object): | |
def __init__(self): | |
self.started_patchers = [] | |
self.mocks = [] | |
def _patch(self, target, checked, **kwargs): | |
patchers = dict((k, _patch_method(target, k, v)) for k, v in kwargs.items()) | |
mocks = {} | |
try: | |
# Keep a list of the patchers that has had .start() *successfully* called | |
for k, patcher in patchers.items(): | |
# Might raise exception on non-existent method | |
mocks[k] = patcher.start() | |
self.started_patchers.append(patcher) | |
# All patchers could be activated | |
self.mocks.append((checked, mocks.values())) | |
return Mocks(mocks) | |
except Exception: | |
self.undo(avoid_call_checks=True) | |
raise | |
def returns(self, target, **kwargs): | |
return self._patch(target, checked=True, **kwargs) | |
def returns_nocheck(self, target, **kwargs): | |
return self._patch(target, checked=False, **kwargs) | |
def raises(self, target, **kwargs): | |
return self._patch(target, checked=True, **kwargs) | |
def raises_nocheck(self, target, **kwargs): | |
return self._patch(target, checked=False, **kwargs) | |
def undo(self, avoid_call_checks=False): | |
for patcher in self.started_patchers: | |
patcher.stop() | |
if avoid_call_checks: | |
return | |
for checked, mocks in self.mocks: | |
if checked: | |
for mock in mocks: | |
assert mock.mock_calls, '%s has no calls!' % repr(mock) | |
@pytest.fixture | |
def stub(request): | |
s = Stub() | |
request.addfinalizer(s.undo) | |
return s |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment