diff options
-rw-r--r-- | docs/conf.py | 2 | ||||
-rw-r--r-- | extendmock.py | 16 | ||||
-rw-r--r-- | mock.py | 1485 | ||||
-rwxr-xr-x | setup.py | 4 | ||||
-rw-r--r-- | tests/__init__.py | 7 | ||||
-rw-r--r-- | tests/support.py | 4 | ||||
-rw-r--r-- | tests/support_with.py | 8 | ||||
-rw-r--r-- | tests/testmagicmethods.py | 535 | ||||
-rw-r--r-- | tests/testmock.py | 613 | ||||
-rw-r--r-- | tests/testmocksignature.py | 48 | ||||
-rw-r--r-- | tests/testpatch.py | 1205 | ||||
-rw-r--r-- | tests/testsentinel.py | 61 | ||||
-rw-r--r-- | tests/testwith.py | 35 |
13 files changed, 2008 insertions, 2015 deletions
diff --git a/docs/conf.py b/docs/conf.py index b6c3838..33616e5 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -176,4 +176,4 @@ latex_documents = [ #latex_appendices = [] # If false, no module index is generated. -latex_use_modindex = False +latex_use_modindex = False
\ No newline at end of file diff --git a/extendmock.py b/extendmock.py index 5728631..07f0ec0 100644 --- a/extendmock.py +++ b/extendmock.py @@ -22,14 +22,14 @@ to mock instances in the same way you mock other attributes:: mock = Mock() mock.__repr__ = lambda self: 'some string' -Note that functions (or callable objects like a Mock instance) that are used for +Note that functions (or callable objects like a Mock instance) that are used for magic methods must take self as the first argument. - + The only unsupported magic methods (that I'm aware of) are: * Used by Mock: __init__, __new__, __getattr__, __setattr__, __delattr__, __call__ * Rare: __dir__, -* Can cause bad interactions with other functionality: +* Can cause bad interactions with other functionality: - __reversed__, __missing__, __del__, __unicode__, __getattribute__ - __get__, __set__, __delete__ @@ -50,12 +50,12 @@ DELEGATE = MISSING = object() def getsignature(func): assert inspect.ismethod(func) or inspect.isfunction(func) regargs, varargs, varkwargs, defaults = inspect.getargspec(func) - + # instance methods need to lose the self argument im_self = getattr(func, 'im_self', None) if im_self is not None: regargs = regargs[1:] - + argnames = list(regargs) if varargs: argnames.append(varargs) @@ -69,7 +69,7 @@ def getsignature(func): def mocksignature(func, mock): signature = getsignature(func) src = "lambda %(signature)s: _mock_(%(signature)s)" % {'signature': signature} - + funcopy = eval(src, dict(_mock_=mock)) funcopy.__name__ = func.__name__ funcopy.__doc__ = func.__doc__ @@ -93,7 +93,7 @@ class MagicMock(Mock): method = _all_magics[name] setattr(self.__class__, name, method) return Mock.__setattr__(self, name, value) - + def __delattr__(self, name): if name in _all_magics and name in self.__class__.__dict__: delattr(self.__class__, name) @@ -123,7 +123,7 @@ def get_method(name): _all_magics = {} for method in sum([methods.split() for methods in [magic_methods, numerics, inplace, right]], []): - name = '__%s__' % method + name = '__%s__' % method _all_magics[name] = get_method(name) import mock @@ -1,743 +1,742 @@ -# mock.py
-# Test tools for mocking and patching.
-# Copyright (C) 2007-2010 Michael Foord & the mock team
-# E-mail: fuzzyman AT voidspace DOT org DOT uk
-
-# mock 0.7.0
-# http://www.voidspace.org.uk/python/mock/
-
-# Released subject to the BSD License
-# Please see http://www.voidspace.org.uk/python/license.shtml
-
-# Scripts maintained at http://www.voidspace.org.uk/python/index.shtml
-# Comments, suggestions and bug reports welcome.
-
-
-__all__ = (
- 'Mock',
- 'MagicMock',
- 'mocksignature',
- 'patch',
- 'patch_object',
- 'sentinel',
- 'DEFAULT'
-)
-
-__version__ = '0.7.0'
-
-import sys
-import warnings
-
-try:
- import inspect
-except ImportError:
- # for alternative platforms that
- # may not have inspect
- inspect = None
-
-try:
- BaseException
-except NameError:
- # Python 2.4 compatibility
- BaseException = Exception
-
-try:
- from functools import wraps
-except ImportError:
- # Python 2.4 compatibility
- def wraps(original):
- def inner(f):
- f.__name__ = original.__name__
- return f
- return inner
-
-try:
- unicode
-except NameError:
- # Python 3
- basestring = unicode = str
-
-try:
- long
-except NameError:
- # Python 3
- long = int
-
-inPy3k = sys.version_info[0] == 3
-
-
-# getsignature and mocksignature heavily "inspired" by
-# the decorator module: http://pypi.python.org/pypi/decorator/
-# by Michele Simionato
-
-def _getsignature(func, skipfirst):
- if inspect is None:
- raise ImportError('inspect module not available')
- assert inspect.ismethod(func) or inspect.isfunction(func)
- regargs, varargs, varkwargs, defaults = inspect.getargspec(func)
-
- # instance methods need to lose the self argument
- if not inPy3k:
- im_self = getattr(func, 'im_self', None)
- else:
- im_self = getattr(func, '__self__', None)
- if im_self is not None:
- regargs = regargs[1:]
-
- assert '_mock_' not in regargs, ("_mock_ is a reserved argument name, can't mock signatures using _mock_")
- if skipfirst:
- regargs = regargs[1:]
- signature = inspect.formatargspec(regargs, varargs, varkwargs, defaults, formatvalue=lambda value: "")
- return signature[1:-1]
-
-
-def _copy_func_details(func, funcopy):
- funcopy.__name__ = func.__name__
- funcopy.__doc__ = func.__doc__
- funcopy.__dict__.update(func.__dict__)
- funcopy.__module__ = func.__module__
- if not inPy3k:
- funcopy.func_defaults = func.func_defaults
- else:
- funcopy.__defaults__ = func.__defaults__
- funcopy.__kwdefaults__ = func.__kwdefaults__
-
-
-def mocksignature(func, mock=None, skipfirst=False):
- """
- mocksignature(func, mock=None, skipfirst=False)
-
- Create a new function with the same signature as `func` that delegates
- to `mock`. If `skipfirst` is True the first argument is skipped, useful
- for methods where `self` needs to be omitted from the new function.
-
- If you don't pass in a `mock` then one will be created for you.
-
- The mock is set as the `mock` attribute of the returned function for easy
- access.
- """
- if mock is None:
- mock = Mock()
- signature = _getsignature(func, skipfirst)
- src = "lambda %(signature)s: _mock_(%(signature)s)" % {'signature': signature}
-
- funcopy = eval(src, dict(_mock_=mock))
- _copy_func_details(func, funcopy)
- funcopy.mock = mock
- return funcopy
-
-
-def _is_magic(name):
- return '__%s__' % name[2:-2] == name
-
-
-class SentinelObject(object):
- "A unique, named, sentinel object."
- def __init__(self, name):
- self.name = name
-
- def __repr__(self):
- return '<SentinelObject "%s">' % self.name
-
-
-class Sentinel(object):
- """Access attributes to return a named object, usable as a sentinel."""
- def __init__(self):
- self._sentinels = {}
-
- def __getattr__(self, name):
- if name == '__bases__':
- # Without this help(mock) raises an exception
- raise AttributeError
- return self._sentinels.setdefault(name, SentinelObject(name))
-
-
-sentinel = Sentinel()
-
-DEFAULT = sentinel.DEFAULT
-
-class OldStyleClass:
- pass
-ClassType = type(OldStyleClass)
-
-def _copy(value):
- if type(value) in (dict, list, tuple, set):
- return type(value)(value)
- return value
-
-
-if inPy3k:
- class_types = type
-else:
- class_types = (type, ClassType)
-
-
-class Mock(object):
- """
- Mock(spec=None, side_effect=None, return_value=DEFAULT, wraps=None)
-
- Create a new ``Mock`` object. ``Mock`` takes several optional arguments
- that specify the behaviour of the Mock object:
-
- * ``spec``: This can be either a list of strings or an existing object (a
- class or instance) that acts as the specification for the mock object. If
- you pass in an object then a list of strings is formed by calling dir on
- the object (excluding unsupported magic attributes and methods). Accessing
- any attribute not in this list will raise an ``AttributeError``.
-
- * ``side_effect``: A function to be called whenever the Mock is called. See
- the :attr:`Mock.side_effect` attribute. Useful for raising exceptions or
- dynamically changing return values. The function is called with the same
- arguments as the mock, and unless it returns :data:`DEFAULT`, the return
- value of this function is used as the return value.
-
- Alternatively ``side_effect`` can be an exception class or instance. In
- this case the exception will be raised when the mock is called.
-
- * ``return_value``: The value returned when the mock is called. By default
- this is a new Mock (created on first access). See the
- :attr:`Mock.return_value` attribute.
-
- * ``wraps``: Item for the mock object to wrap. If ``wraps`` is not None
- then calling the Mock will pass the call through to the wrapped object
- (returning the real result and ignoring ``return_value``). Attribute
- access on the mock will return a Mock object that wraps the corresponding
- attribute of the wrapped object (so attempting to access an attribute that
- doesn't exist will raise an ``AttributeError``).
-
- If the mock has an explicit ``return_value`` set then calls are not passed
- to the wrapped object and the ``return_value`` is returned instead.
- """
- def __new__(cls, *args, **kw):
- class Mock(cls):
- # every instance has its own class
- # so we can create magic methods on the
- # class without stomping on other mocks
- pass
- return object.__new__(Mock)
-
- def __init__(self, spec=None, side_effect=None, return_value=DEFAULT,
- name=None, parent=None, wraps=None):
- self._parent = parent
- self._name = name
- if spec is not None and not isinstance(spec, list):
- spec = [member for member in dir(spec) if not _is_magic(member)]
-
- self._methods = spec
- self._children = {}
- self._return_value = return_value
- self.side_effect = side_effect
- self._wraps = wraps
-
- self.reset_mock()
-
-
- def reset_mock(self):
- "Restore the mock object to its initial state."
- self.called = False
- self.call_args = None
- self.call_count = 0
- self.call_args_list = []
- self.method_calls = []
- for child in self._children.values():
- child.reset_mock()
- if isinstance(self._return_value, Mock):
- self._return_value.reset_mock()
-
-
- def __get_return_value(self):
- if self._return_value is DEFAULT:
- self._return_value = Mock()
- return self._return_value
-
- def __set_return_value(self, value):
- self._return_value = value
-
- __return_value_doc = "The value to be returned when the mock is called."
-
- return_value = property(__get_return_value, __set_return_value,
- __return_value_doc)
-
-
- def __call__(self, *args, **kwargs):
- self.called = True
- self.call_count += 1
- self.call_args = callargs((args, kwargs))
- self.call_args_list.append(callargs((args, kwargs)))
-
- parent = self._parent
- name = self._name
- while parent is not None:
- parent.method_calls.append(callargs((name, args, kwargs)))
- if parent._parent is None:
- break
- name = parent._name + '.' + name
- parent = parent._parent
-
- ret_val = DEFAULT
- if self.side_effect is not None:
- if (isinstance(self.side_effect, BaseException) or
- isinstance(self.side_effect, class_types) and
- issubclass(self.side_effect, BaseException)):
- raise self.side_effect
-
- ret_val = self.side_effect(*args, **kwargs)
- if ret_val is DEFAULT:
- ret_val = self.return_value
-
- if self._wraps is not None and self._return_value is DEFAULT:
- return self._wraps(*args, **kwargs)
- if ret_val is DEFAULT:
- ret_val = self.return_value
- return ret_val
-
-
- def __getattr__(self, name):
- if self._methods is not None:
- if name not in self._methods:
- raise AttributeError("Mock object has no attribute '%s'" % name)
- elif _is_magic(name):
- raise AttributeError(name)
-
- if name not in self._children:
- wraps = None
- if self._wraps is not None:
- wraps = getattr(self._wraps, name)
- self._children[name] = Mock(parent=self, name=name, wraps=wraps)
-
- return self._children[name]
-
- def __setattr__(self, name, value):
- if name in _all_magics:
- if not isinstance(value, Mock):
- setattr(self.__class__, name, get_method(name, value))
- original = value
- real = lambda *args, **kw: original(self, *args, **kw)
- value = mocksignature(value, real, skipfirst=True)
- else:
- setattr(self.__class__, name, value)
- return object.__setattr__(self, name, value)
-
- def __delattr__(self, name):
- if name in _all_magics and name in self.__class__.__dict__:
- delattr(self.__class__, name)
- return object.__delattr__(self, name)
-
- def assert_called_with(self, *args, **kwargs):
- """
- assert that the mock was called with the specified arguments.
-
- Raises an AttributeError if the args and keyword args passed in are
- different to the last call to the mock.
- """
- assert self.call_args == (args, kwargs), 'Expected: %s\nCalled with: %s' % ((args, kwargs), self.call_args)
-
-
-class callargs(tuple):
- """
- A tuple for holding the results of a call to a mock, either in the form
- `(args, kwargs)` or `(name, args, kwargs)`.
-
- If args or kwargs are empty then a callargs tuple will compare equal to
- a tuple without those values. This makes comparisons less verbose::
-
- callargs('name', (), {}) == ('name',)
- callargs('name', (1,), {}) == ('name', (1,))
- callargs((), {'a': 'b'}) == ({'a': 'b'},)
- """
- def __eq__(self, other):
- if len(self) == 3:
- if other[0] != self[0]:
- return False
- args_kwargs = self[1:]
- other_args_kwargs = other[1:]
- else:
- args_kwargs = tuple(self)
- other_args_kwargs = other
-
- if len(other_args_kwargs) == 0:
- other_args, other_kwargs = (), {}
- elif len(other_args_kwargs) == 1:
- if isinstance(other_args_kwargs[0], tuple):
- other_args = other_args_kwargs[0]
- other_kwargs = {}
- else:
- other_args = ()
- other_kwargs = other_args_kwargs[0]
- else:
- other_args, other_kwargs = other_args_kwargs
-
- return tuple(args_kwargs) == (other_args, other_kwargs)
-
-def _dot_lookup(thing, comp, import_path):
- try:
- return getattr(thing, comp)
- except AttributeError:
- __import__(import_path)
- return getattr(thing, comp)
-
-
-def _importer(target):
- components = target.split('.')
- import_path = components.pop(0)
- thing = __import__(import_path)
-
- for comp in components:
- import_path += ".%s" % comp
- thing = _dot_lookup(thing, comp, import_path)
- return thing
-
-
-class _patch(object):
- def __init__(self, target, attribute, new, spec, create, mocksignature):
- self.target = target
- self.attribute = attribute
- self.new = new
- self.spec = spec
- self.create = create
- self.has_local = False
- self.mocksignature = mocksignature
-
-
- def copy(self):
- return _patch(self.target, self.attribute, self.new,
- self.spec, self.create, self.mocksignature)
-
-
- def __call__(self, func):
- if isinstance(func, class_types):
- return self.decorate_class(func)
- else:
- return self.decorate_callable(func)
-
- def decorate_class(self, klass):
- for attr in dir(klass):
- attr_value = getattr(klass, attr)
- if attr.startswith("test") and hasattr(attr_value, "__call__"):
- setattr(klass, attr, self.copy()(attr_value))
- return klass
-
- def decorate_callable(self, func):
- if hasattr(func, 'patchings'):
- func.patchings.append(self)
- return func
-
- @wraps(func)
- def patched(*args, **keywargs):
- # don't use a with here (backwards compatability with 2.5)
- extra_args = []
- for patching in patched.patchings:
- arg = patching.__enter__()
- if patching.new is DEFAULT:
- extra_args.append(arg)
- args += tuple(extra_args)
- try:
- return func(*args, **keywargs)
- finally:
- for patching in reversed(getattr(patched, 'patchings', [])):
- patching.__exit__()
-
- patched.patchings = [self]
- if hasattr(func, 'func_code'):
- # not in Python 3
- patched.compat_co_firstlineno = getattr(func, "compat_co_firstlineno",
- func.func_code.co_firstlineno)
- return patched
-
-
- def get_original(self):
- target = self.target
- name = self.attribute
- create = self.create
-
- original = DEFAULT
- if _has_local_attr(target, name):
- try:
- original = target.__dict__[name]
- except AttributeError:
- # for instances of classes with slots, they have no __dict__
- original = getattr(target, name)
- elif not create and not hasattr(target, name):
- raise AttributeError("%s does not have the attribute %r" % (target, name))
- return original
-
-
- def __enter__(self):
- new, spec, = self.new, self.spec
- original = self.get_original()
- if new is DEFAULT:
- # XXXX what if original is DEFAULT - shouldn't use it as a spec
- inherit = False
- if spec == True:
- # set spec to the object we are replacing
- spec = original
- if isinstance(spec, class_types):
- inherit = True
- new = Mock(spec=spec)
- if inherit:
- new.return_value = Mock(spec=spec)
- new_attr = new
- if self.mocksignature:
- new_attr = mocksignature(original, new)
-
- self.temp_original = original
- setattr(self.target, self.attribute, new_attr)
- return new
-
-
- def __exit__(self, *_):
- if self.temp_original is not DEFAULT:
- setattr(self.target, self.attribute, self.temp_original)
- else:
- delattr(self.target, self.attribute)
- del self.temp_original
-
-
-def _patch_object(target, attribute, new=DEFAULT, spec=None, create=False, mocksignature=False):
- """
- patch.object(target, attribute, new=DEFAULT, spec=None, create=False, mocksignature=False)
-
- patch the named member (`attribute`) on an object (`target`) with a mock
- object.
-
- Arguments new, spec, create and mocksignature have the same meaning as for
- patch.
- """
- return _patch(target, attribute, new, spec, create, mocksignature)
-
-def patch_object(*args, **kwargs):
- "A deprecated form of patch.object(...)"
- warnings.warn(('Please use patch.object instead.'), DeprecationWarning, 2)
- return _patch_object(*args, **kwargs)
-
-def patch(target, new=DEFAULT, spec=None, create=False, mocksignature=False):
- """
- patch(target, new=DEFAULT, spec=None, create=False, mocksignature=False)
-
- ``patch`` acts as a function decorator or a context manager. Inside the body
- of the function or with statement, the ``target`` (specified in the form
- 'PackageName.ModuleName.ClassName') is patched with a ``new`` object. When the
- function/with statement exits the patch is undone.
-
- The target is imported and the specified attribute patched with the new object
- - so it must be importable from the environment you are calling the decorator
- from.
-
- If ``new`` is omitted, then a new ``Mock`` is created and passed in as an
- extra argument to the decorated function.
-
- The ``spec`` keyword argument is passed to the ``Mock`` if patch is creating
- one for you.
-
- In addition you can pass ``spec=True``, which causes patch to pass in the
- object being mocked as the spec object.
-
- If ``mocksignature`` is True then the patch will be done with a function
- created by mocking the one being replaced.
-
- patch.dict(...) and patch.object(...) are available for alternate use-cases.
- """
- try:
- target, attribute = target.rsplit('.', 1)
- except (TypeError, ValueError):
- raise TypeError("Need a valid target to patch. You supplied: %r" % (target,))
- target = _importer(target)
- return _patch(target, attribute, new, spec, create, mocksignature)
-
-class _patch_dict(object):
- """
- patch.dict(in_dict, values=(), clear=False)
-
- Patch a dictionary and restore the dictionary to its original state after
- the test.
-
- `in_dict` can be a dictionary or a mapping like container. If it is a
- mapping then it must at least support getting, setting and deleting items
- plus iterating over keys.
-
- `in_dict` can also be a string specifying the name of the dictionary, which
- will then be fetched by importing it.
-
- `values` can be a dictionary of values to set in the dictionary. `values`
- can also be an iterable of ``(key, value)`` pairs.
-
- If `clear` is True then the dictionary will be cleared before the new
- values are set.
- """
-
- def __init__(self, in_dict, values=(), clear=False):
- if isinstance(in_dict, basestring):
- in_dict = _importer(in_dict)
- self.in_dict = in_dict
- # support any argument supported by dict(...) constructor
- self.values = dict(values)
- self.clear = clear
- self._original = None
-
- def __call__(self, f):
- @wraps(f)
- def _inner(*args, **kw):
- self._patch_dict()
- try:
- return f(*args, **kw)
- finally:
- self._unpatch_dict()
-
- return _inner
-
- def __enter__(self):
- self._patch_dict()
-
- def _patch_dict(self):
- values = self.values
- in_dict = self.in_dict
- clear = self.clear
-
- try:
- original = in_dict.copy()
- except AttributeError:
- # dict like object with no copy method
- # must support iteration over keys
- original = {}
- for key in in_dict:
- original[key] = in_dict[key]
- self._original = original
-
- if clear:
- _clear_dict(in_dict)
-
- try:
- in_dict.update(values)
- except AttributeError:
- # dict like object with no update method
- for key in values:
- in_dict[key] = values[key]
-
- def _unpatch_dict(self):
- in_dict = self.in_dict
- original = self._original
-
- _clear_dict(in_dict)
-
- try:
- in_dict.update(original)
- except AttributeError:
- for key in original:
- in_dict[key] = original[key]
-
-
- def __exit__(self, *args):
- self._unpatch_dict()
- return False
-
-
-def _clear_dict(in_dict):
- try:
- in_dict.clear()
- except AttributeError:
- keys = list(in_dict)
- for key in keys:
- del in_dict[key]
-
-
-patch.object = _patch_object
-patch.dict = _patch_dict
-
-def _has_local_attr(obj, name):
- try:
- return name in vars(obj)
- except TypeError:
- # objects without a __dict__
- return hasattr(obj, name)
-
-
-magic_methods = (
- "lt le gt ge eq ne "
- "getitem setitem delitem "
- "len contains iter "
- "hash repr str "
- "enter exit "
- "divmod neg pos abs invert "
- "complex int float index "
-)
-
-numerics = "add sub mul div truediv floordiv mod lshift rshift and xor or pow "
-inplace = ' '.join('i%s' % n for n in numerics.split())
-right = ' '.join('r%s' % n for n in numerics.split())
-extra = ''
-if inPy3k:
- extra = 'bool next '
-else:
- extra = 'unicode long nonzero oct hex '
-# __truediv__ and __rtruediv__ not available in Python 3 either
-
-# not including __prepare__, __instancecheck__, __subclasscheck__
-# (as they are metaclass methods)
-# __del__ is not supported at all as it causes problems if it exists
-
-_non_defaults = set('__%s__' % method for method in [
- 'cmp', 'getslice', 'setslice', 'coerce', 'subclasses',
- 'dir', 'format', 'get', 'set', 'delete', 'reversed',
- 'missing',
-])
-
-def get_method(name, func):
- def method(self, *args, **kw):
- return func(self, *args, **kw)
- method.__name__ = name
- return method
-
-_magics = set('__%s__' % method for method in ' '.join([magic_methods, numerics, inplace, right, extra]).split())
-
-_all_magics = _magics | _non_defaults
-
-
-_side_effects = {
- '__hash__': lambda self: object.__hash__(self),
- '__repr__': lambda self: object.__repr__(self),
- '__str__': lambda self: object.__str__(self),
- '__unicode__': lambda self: unicode(object.__str__(self)),
-}
-
-_return_values = {
- '__int__': 0,
- '__contains__': False,
- '__len__': 0,
- '__iter__': iter([]),
- '__exit__': False,
- '__complex__': 0j,
- '__float__': 0.0,
- '__bool__': True,
- '__nonzero__': True,
- '__oct__': '0',
- '__hex__': '0x0',
- '__long__': long(0),
- '__index__': 0,
-}
-
-def _set_return_value(mock, method, name):
- if name in _side_effects:
- func = _side_effects[name]
- def wrap(*args, **kw):
- if method._return_value is DEFAULT:
- return func(mock)
- return method._return_value
- method.side_effect = wrap
- elif name in _return_values:
- method.return_value = _return_values[name]
-
-
-class MagicMock(Mock):
- """
- MagicMock is a subclass of :Mock with default implementations
- of most of the magic methods. You can use MagicMock without having to
- configure the magic methods yourself.
- """
- def __init__(self, *args, **kw):
- Mock.__init__(self, *args, **kw)
- for entry in _magics:
- # could specify parent?
- m = Mock()
- setattr(self, entry, m)
- _set_return_value(self, m, entry)
-
+# mock.py +# Test tools for mocking and patching. +# Copyright (C) 2007-2010 Michael Foord & the mock team +# E-mail: fuzzyman AT voidspace DOT org DOT uk + +# mock 0.7.0 +# http://www.voidspace.org.uk/python/mock/ + +# Released subject to the BSD License +# Please see http://www.voidspace.org.uk/python/license.shtml + +# Scripts maintained at http://www.voidspace.org.uk/python/index.shtml +# Comments, suggestions and bug reports welcome. + + +__all__ = ( + 'Mock', + 'MagicMock', + 'mocksignature', + 'patch', + 'patch_object', + 'sentinel', + 'DEFAULT' +) + +__version__ = '0.7.0' + +import sys +import warnings + +try: + import inspect +except ImportError: + # for alternative platforms that + # may not have inspect + inspect = None + +try: + BaseException +except NameError: + # Python 2.4 compatibility + BaseException = Exception + +try: + from functools import wraps +except ImportError: + # Python 2.4 compatibility + def wraps(original): + def inner(f): + f.__name__ = original.__name__ + return f + return inner + +try: + unicode +except NameError: + # Python 3 + basestring = unicode = str + +try: + long +except NameError: + # Python 3 + long = int + +inPy3k = sys.version_info[0] == 3 + + +# getsignature and mocksignature heavily "inspired" by +# the decorator module: http://pypi.python.org/pypi/decorator/ +# by Michele Simionato + +def _getsignature(func, skipfirst): + if inspect is None: + raise ImportError('inspect module not available') + assert inspect.ismethod(func) or inspect.isfunction(func) + regargs, varargs, varkwargs, defaults = inspect.getargspec(func) + + # instance methods need to lose the self argument + if not inPy3k: + im_self = getattr(func, 'im_self', None) + else: + im_self = getattr(func, '__self__', None) + if im_self is not None: + regargs = regargs[1:] + + assert '_mock_' not in regargs, ("_mock_ is a reserved argument name, can't mock signatures using _mock_") + if skipfirst: + regargs = regargs[1:] + signature = inspect.formatargspec(regargs, varargs, varkwargs, defaults, formatvalue=lambda value: "") + return signature[1:-1] + + +def _copy_func_details(func, funcopy): + funcopy.__name__ = func.__name__ + funcopy.__doc__ = func.__doc__ + funcopy.__dict__.update(func.__dict__) + funcopy.__module__ = func.__module__ + if not inPy3k: + funcopy.func_defaults = func.func_defaults + else: + funcopy.__defaults__ = func.__defaults__ + funcopy.__kwdefaults__ = func.__kwdefaults__ + + +def mocksignature(func, mock=None, skipfirst=False): + """ + mocksignature(func, mock=None, skipfirst=False) + + Create a new function with the same signature as `func` that delegates + to `mock`. If `skipfirst` is True the first argument is skipped, useful + for methods where `self` needs to be omitted from the new function. + + If you don't pass in a `mock` then one will be created for you. + + The mock is set as the `mock` attribute of the returned function for easy + access. + """ + if mock is None: + mock = Mock() + signature = _getsignature(func, skipfirst) + src = "lambda %(signature)s: _mock_(%(signature)s)" % {'signature': signature} + + funcopy = eval(src, dict(_mock_=mock)) + _copy_func_details(func, funcopy) + funcopy.mock = mock + return funcopy + + +def _is_magic(name): + return '__%s__' % name[2:-2] == name + + +class SentinelObject(object): + "A unique, named, sentinel object." + def __init__(self, name): + self.name = name + + def __repr__(self): + return '<SentinelObject "%s">' % self.name + + +class Sentinel(object): + """Access attributes to return a named object, usable as a sentinel.""" + def __init__(self): + self._sentinels = {} + + def __getattr__(self, name): + if name == '__bases__': + # Without this help(mock) raises an exception + raise AttributeError + return self._sentinels.setdefault(name, SentinelObject(name)) + + +sentinel = Sentinel() + +DEFAULT = sentinel.DEFAULT + +class OldStyleClass: + pass +ClassType = type(OldStyleClass) + +def _copy(value): + if type(value) in (dict, list, tuple, set): + return type(value)(value) + return value + + +if inPy3k: + class_types = type +else: + class_types = (type, ClassType) + + +class Mock(object): + """ + Mock(spec=None, side_effect=None, return_value=DEFAULT, wraps=None) + + Create a new ``Mock`` object. ``Mock`` takes several optional arguments + that specify the behaviour of the Mock object: + + * ``spec``: This can be either a list of strings or an existing object (a + class or instance) that acts as the specification for the mock object. If + you pass in an object then a list of strings is formed by calling dir on + the object (excluding unsupported magic attributes and methods). Accessing + any attribute not in this list will raise an ``AttributeError``. + + * ``side_effect``: A function to be called whenever the Mock is called. See + the :attr:`Mock.side_effect` attribute. Useful for raising exceptions or + dynamically changing return values. The function is called with the same + arguments as the mock, and unless it returns :data:`DEFAULT`, the return + value of this function is used as the return value. + + Alternatively ``side_effect`` can be an exception class or instance. In + this case the exception will be raised when the mock is called. + + * ``return_value``: The value returned when the mock is called. By default + this is a new Mock (created on first access). See the + :attr:`Mock.return_value` attribute. + + * ``wraps``: Item for the mock object to wrap. If ``wraps`` is not None + then calling the Mock will pass the call through to the wrapped object + (returning the real result and ignoring ``return_value``). Attribute + access on the mock will return a Mock object that wraps the corresponding + attribute of the wrapped object (so attempting to access an attribute that + doesn't exist will raise an ``AttributeError``). + + If the mock has an explicit ``return_value`` set then calls are not passed + to the wrapped object and the ``return_value`` is returned instead. + """ + def __new__(cls, *args, **kw): + class Mock(cls): + # every instance has its own class + # so we can create magic methods on the + # class without stomping on other mocks + pass + return object.__new__(Mock) + + def __init__(self, spec=None, side_effect=None, return_value=DEFAULT, + name=None, parent=None, wraps=None): + self._parent = parent + self._name = name + if spec is not None and not isinstance(spec, list): + spec = [member for member in dir(spec) if not _is_magic(member)] + + self._methods = spec + self._children = {} + self._return_value = return_value + self.side_effect = side_effect + self._wraps = wraps + + self.reset_mock() + + + def reset_mock(self): + "Restore the mock object to its initial state." + self.called = False + self.call_args = None + self.call_count = 0 + self.call_args_list = [] + self.method_calls = [] + for child in self._children.values(): + child.reset_mock() + if isinstance(self._return_value, Mock): + self._return_value.reset_mock() + + + def __get_return_value(self): + if self._return_value is DEFAULT: + self._return_value = Mock() + return self._return_value + + def __set_return_value(self, value): + self._return_value = value + + __return_value_doc = "The value to be returned when the mock is called." + + return_value = property(__get_return_value, __set_return_value, + __return_value_doc) + + + def __call__(self, *args, **kwargs): + self.called = True + self.call_count += 1 + self.call_args = callargs((args, kwargs)) + self.call_args_list.append(callargs((args, kwargs))) + + parent = self._parent + name = self._name + while parent is not None: + parent.method_calls.append(callargs((name, args, kwargs))) + if parent._parent is None: + break + name = parent._name + '.' + name + parent = parent._parent + + ret_val = DEFAULT + if self.side_effect is not None: + if (isinstance(self.side_effect, BaseException) or + isinstance(self.side_effect, class_types) and + issubclass(self.side_effect, BaseException)): + raise self.side_effect + + ret_val = self.side_effect(*args, **kwargs) + if ret_val is DEFAULT: + ret_val = self.return_value + + if self._wraps is not None and self._return_value is DEFAULT: + return self._wraps(*args, **kwargs) + if ret_val is DEFAULT: + ret_val = self.return_value + return ret_val + + + def __getattr__(self, name): + if self._methods is not None: + if name not in self._methods: + raise AttributeError("Mock object has no attribute '%s'" % name) + elif _is_magic(name): + raise AttributeError(name) + + if name not in self._children: + wraps = None + if self._wraps is not None: + wraps = getattr(self._wraps, name) + self._children[name] = Mock(parent=self, name=name, wraps=wraps) + + return self._children[name] + + def __setattr__(self, name, value): + if name in _all_magics: + if not isinstance(value, Mock): + setattr(self.__class__, name, get_method(name, value)) + original = value + real = lambda *args, **kw: original(self, *args, **kw) + value = mocksignature(value, real, skipfirst=True) + else: + setattr(self.__class__, name, value) + return object.__setattr__(self, name, value) + + def __delattr__(self, name): + if name in _all_magics and name in self.__class__.__dict__: + delattr(self.__class__, name) + return object.__delattr__(self, name) + + def assert_called_with(self, *args, **kwargs): + """ + assert that the mock was called with the specified arguments. + + Raises an AttributeError if the args and keyword args passed in are + different to the last call to the mock. + """ + assert self.call_args == (args, kwargs), 'Expected: %s\nCalled with: %s' % ((args, kwargs), self.call_args) + + +class callargs(tuple): + """ + A tuple for holding the results of a call to a mock, either in the form + `(args, kwargs)` or `(name, args, kwargs)`. + + If args or kwargs are empty then a callargs tuple will compare equal to + a tuple without those values. This makes comparisons less verbose:: + + callargs('name', (), {}) == ('name',) + callargs('name', (1,), {}) == ('name', (1,)) + callargs((), {'a': 'b'}) == ({'a': 'b'},) + """ + def __eq__(self, other): + if len(self) == 3: + if other[0] != self[0]: + return False + args_kwargs = self[1:] + other_args_kwargs = other[1:] + else: + args_kwargs = tuple(self) + other_args_kwargs = other + + if len(other_args_kwargs) == 0: + other_args, other_kwargs = (), {} + elif len(other_args_kwargs) == 1: + if isinstance(other_args_kwargs[0], tuple): + other_args = other_args_kwargs[0] + other_kwargs = {} + else: + other_args = () + other_kwargs = other_args_kwargs[0] + else: + other_args, other_kwargs = other_args_kwargs + + return tuple(args_kwargs) == (other_args, other_kwargs) + +def _dot_lookup(thing, comp, import_path): + try: + return getattr(thing, comp) + except AttributeError: + __import__(import_path) + return getattr(thing, comp) + + +def _importer(target): + components = target.split('.') + import_path = components.pop(0) + thing = __import__(import_path) + + for comp in components: + import_path += ".%s" % comp + thing = _dot_lookup(thing, comp, import_path) + return thing + + +class _patch(object): + def __init__(self, target, attribute, new, spec, create, mocksignature): + self.target = target + self.attribute = attribute + self.new = new + self.spec = spec + self.create = create + self.has_local = False + self.mocksignature = mocksignature + + + def copy(self): + return _patch(self.target, self.attribute, self.new, + self.spec, self.create, self.mocksignature) + + + def __call__(self, func): + if isinstance(func, class_types): + return self.decorate_class(func) + else: + return self.decorate_callable(func) + + def decorate_class(self, klass): + for attr in dir(klass): + attr_value = getattr(klass, attr) + if attr.startswith("test") and hasattr(attr_value, "__call__"): + setattr(klass, attr, self.copy()(attr_value)) + return klass + + def decorate_callable(self, func): + if hasattr(func, 'patchings'): + func.patchings.append(self) + return func + + @wraps(func) + def patched(*args, **keywargs): + # don't use a with here (backwards compatability with 2.5) + extra_args = [] + for patching in patched.patchings: + arg = patching.__enter__() + if patching.new is DEFAULT: + extra_args.append(arg) + args += tuple(extra_args) + try: + return func(*args, **keywargs) + finally: + for patching in reversed(getattr(patched, 'patchings', [])): + patching.__exit__() + + patched.patchings = [self] + if hasattr(func, 'func_code'): + # not in Python 3 + patched.compat_co_firstlineno = getattr(func, "compat_co_firstlineno", + func.func_code.co_firstlineno) + return patched + + + def get_original(self): + target = self.target + name = self.attribute + create = self.create + + original = DEFAULT + if _has_local_attr(target, name): + try: + original = target.__dict__[name] + except AttributeError: + # for instances of classes with slots, they have no __dict__ + original = getattr(target, name) + elif not create and not hasattr(target, name): + raise AttributeError("%s does not have the attribute %r" % (target, name)) + return original + + + def __enter__(self): + new, spec, = self.new, self.spec + original = self.get_original() + if new is DEFAULT: + # XXXX what if original is DEFAULT - shouldn't use it as a spec + inherit = False + if spec == True: + # set spec to the object we are replacing + spec = original + if isinstance(spec, class_types): + inherit = True + new = Mock(spec=spec) + if inherit: + new.return_value = Mock(spec=spec) + new_attr = new + if self.mocksignature: + new_attr = mocksignature(original, new) + + self.temp_original = original + setattr(self.target, self.attribute, new_attr) + return new + + + def __exit__(self, *_): + if self.temp_original is not DEFAULT: + setattr(self.target, self.attribute, self.temp_original) + else: + delattr(self.target, self.attribute) + del self.temp_original + + +def _patch_object(target, attribute, new=DEFAULT, spec=None, create=False, mocksignature=False): + """ + patch.object(target, attribute, new=DEFAULT, spec=None, create=False, mocksignature=False) + + patch the named member (`attribute`) on an object (`target`) with a mock + object. + + Arguments new, spec, create and mocksignature have the same meaning as for + patch. + """ + return _patch(target, attribute, new, spec, create, mocksignature) + +def patch_object(*args, **kwargs): + "A deprecated form of patch.object(...)" + warnings.warn(('Please use patch.object instead.'), DeprecationWarning, 2) + return _patch_object(*args, **kwargs) + +def patch(target, new=DEFAULT, spec=None, create=False, mocksignature=False): + """ + patch(target, new=DEFAULT, spec=None, create=False, mocksignature=False) + + ``patch`` acts as a function decorator or a context manager. Inside the body + of the function or with statement, the ``target`` (specified in the form + 'PackageName.ModuleName.ClassName') is patched with a ``new`` object. When the + function/with statement exits the patch is undone. + + The target is imported and the specified attribute patched with the new object + - so it must be importable from the environment you are calling the decorator + from. + + If ``new`` is omitted, then a new ``Mock`` is created and passed in as an + extra argument to the decorated function. + + The ``spec`` keyword argument is passed to the ``Mock`` if patch is creating + one for you. + + In addition you can pass ``spec=True``, which causes patch to pass in the + object being mocked as the spec object. + + If ``mocksignature`` is True then the patch will be done with a function + created by mocking the one being replaced. + + patch.dict(...) and patch.object(...) are available for alternate use-cases. + """ + try: + target, attribute = target.rsplit('.', 1) + except (TypeError, ValueError): + raise TypeError("Need a valid target to patch. You supplied: %r" % (target,)) + target = _importer(target) + return _patch(target, attribute, new, spec, create, mocksignature) + +class _patch_dict(object): + """ + patch.dict(in_dict, values=(), clear=False) + + Patch a dictionary and restore the dictionary to its original state after + the test. + + `in_dict` can be a dictionary or a mapping like container. If it is a + mapping then it must at least support getting, setting and deleting items + plus iterating over keys. + + `in_dict` can also be a string specifying the name of the dictionary, which + will then be fetched by importing it. + + `values` can be a dictionary of values to set in the dictionary. `values` + can also be an iterable of ``(key, value)`` pairs. + + If `clear` is True then the dictionary will be cleared before the new + values are set. + """ + + def __init__(self, in_dict, values=(), clear=False): + if isinstance(in_dict, basestring): + in_dict = _importer(in_dict) + self.in_dict = in_dict + # support any argument supported by dict(...) constructor + self.values = dict(values) + self.clear = clear + self._original = None + + def __call__(self, f): + @wraps(f) + def _inner(*args, **kw): + self._patch_dict() + try: + return f(*args, **kw) + finally: + self._unpatch_dict() + + return _inner + + def __enter__(self): + self._patch_dict() + + def _patch_dict(self): + values = self.values + in_dict = self.in_dict + clear = self.clear + + try: + original = in_dict.copy() + except AttributeError: + # dict like object with no copy method + # must support iteration over keys + original = {} + for key in in_dict: + original[key] = in_dict[key] + self._original = original + + if clear: + _clear_dict(in_dict) + + try: + in_dict.update(values) + except AttributeError: + # dict like object with no update method + for key in values: + in_dict[key] = values[key] + + def _unpatch_dict(self): + in_dict = self.in_dict + original = self._original + + _clear_dict(in_dict) + + try: + in_dict.update(original) + except AttributeError: + for key in original: + in_dict[key] = original[key] + + + def __exit__(self, *args): + self._unpatch_dict() + return False + + +def _clear_dict(in_dict): + try: + in_dict.clear() + except AttributeError: + keys = list(in_dict) + for key in keys: + del in_dict[key] + + +patch.object = _patch_object +patch.dict = _patch_dict + +def _has_local_attr(obj, name): + try: + return name in vars(obj) + except TypeError: + # objects without a __dict__ + return hasattr(obj, name) + + +magic_methods = ( + "lt le gt ge eq ne " + "getitem setitem delitem " + "len contains iter " + "hash repr str " + "enter exit " + "divmod neg pos abs invert " + "complex int float index " +) + +numerics = "add sub mul div truediv floordiv mod lshift rshift and xor or pow " +inplace = ' '.join('i%s' % n for n in numerics.split()) +right = ' '.join('r%s' % n for n in numerics.split()) +extra = '' +if inPy3k: + extra = 'bool next ' +else: + extra = 'unicode long nonzero oct hex ' +# __truediv__ and __rtruediv__ not available in Python 3 either + +# not including __prepare__, __instancecheck__, __subclasscheck__ +# (as they are metaclass methods) +# __del__ is not supported at all as it causes problems if it exists + +_non_defaults = set('__%s__' % method for method in [ + 'cmp', 'getslice', 'setslice', 'coerce', 'subclasses', + 'dir', 'format', 'get', 'set', 'delete', 'reversed', + 'missing', +]) + +def get_method(name, func): + def method(self, *args, **kw): + return func(self, *args, **kw) + method.__name__ = name + return method + +_magics = set('__%s__' % method for method in ' '.join([magic_methods, numerics, inplace, right, extra]).split()) + +_all_magics = _magics | _non_defaults + + +_side_effects = { + '__hash__': lambda self: object.__hash__(self), + '__repr__': lambda self: object.__repr__(self), + '__str__': lambda self: object.__str__(self), + '__unicode__': lambda self: unicode(object.__str__(self)), +} + +_return_values = { + '__int__': 0, + '__contains__': False, + '__len__': 0, + '__iter__': iter([]), + '__exit__': False, + '__complex__': 0j, + '__float__': 0.0, + '__bool__': True, + '__nonzero__': True, + '__oct__': '0', + '__hex__': '0x0', + '__long__': long(0), + '__index__': 0, +} + +def _set_return_value(mock, method, name): + if name in _side_effects: + func = _side_effects[name] + def wrap(*args, **kw): + if method._return_value is DEFAULT: + return func(mock) + return method._return_value + method.side_effect = wrap + elif name in _return_values: + method.return_value = _return_values[name] + + +class MagicMock(Mock): + """ + MagicMock is a subclass of :Mock with default implementations + of most of the magic methods. You can use MagicMock without having to + configure the magic methods yourself. + """ + def __init__(self, *args, **kw): + Mock.__init__(self, *args, **kw) + for entry in _magics: + # could specify parent? + m = Mock() + setattr(self, entry, m) + _set_return_value(self, m, entry) @@ -49,7 +49,7 @@ setup( name=NAME, version=__version__, py_modules=MODULES, - + # metadata for upload to PyPI author=AUTHOR, author_email=AUTHOR_EMAIL, @@ -58,4 +58,4 @@ setup( keywords=KEYWORDS, url=URL, classifiers=CLASSIFIERS, -) +)
\ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py index ca641cb..6d5f87c 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,4 +1,3 @@ -# Copyright (C) 2007-2010 Michael Foord & the mock team
-# E-mail: fuzzyman AT voidspace DOT org DOT uk
-# http://www.voidspace.org.uk/python/mock/
-
+# Copyright (C) 2007-2010 Michael Foord & the mock team +# E-mail: fuzzyman AT voidspace DOT org DOT uk +# http://www.voidspace.org.uk/python/mock/ diff --git a/tests/support.py b/tests/support.py index 5ea466f..c3c4189 100644 --- a/tests/support.py +++ b/tests/support.py @@ -24,6 +24,6 @@ with_available = sys.version_info[:2] >= (2, 5) class SomeClass(object): class_attribute = None - + def wibble(self): - pass + pass
\ No newline at end of file diff --git a/tests/support_with.py b/tests/support_with.py index f9cb6ce..9c04691 100644 --- a/tests/support_with.py +++ b/tests/support_with.py @@ -43,14 +43,14 @@ except ImportError: self._record = record self._module = sys.modules['warnings'] self._entered = False - + def __repr__(self): args = [] if self._record: args.append("record=True") name = type(self).__name__ return "%s(%s)" % (name, ", ".join(args)) - + def __enter__(self): if self._entered: raise RuntimeError("Cannot enter %r twice" % self) @@ -66,7 +66,7 @@ except ImportError: return log else: return None - + def __exit__(self, *exc_info): if not self._entered: raise RuntimeError("Cannot exit %r without entering first" % self) @@ -90,4 +90,4 @@ def examine_warnings(func): def wrapper(): with catch_warnings(record=True) as ws: func(ws) - return wrapper + return wrapper
\ No newline at end of file diff --git a/tests/testmagicmethods.py b/tests/testmagicmethods.py index f03b60a..9495764 100644 --- a/tests/testmagicmethods.py +++ b/tests/testmagicmethods.py @@ -1,268 +1,267 @@ -# Copyright (C) 2007-2010 Michael Foord & the mock team
-# E-mail: fuzzyman AT voidspace DOT org DOT uk
-# http://www.voidspace.org.uk/python/mock/
-
-from tests.support import unittest2, inPy3k
-
-try:
- unicode
-except NameError:
- # Python 3
- unicode = str
- long = int
-
-import inspect
-from mock import Mock, MagicMock, _magics
-
-
-
-class TestMockingMagicMethods(unittest2.TestCase):
-
- def testDeletingMagicMethods(self):
- mock = Mock()
- self.assertFalse(hasattr(mock, '__getitem__'))
-
- mock.__getitem__ = Mock()
- self.assertTrue(hasattr(mock, '__getitem__'))
-
- del mock.__getitem__
- self.assertFalse(hasattr(mock, '__getitem__'))
-
-
- def testMagicMethodWrapping(self):
- mock = Mock()
- def f(self, name):
- return self, 'fish'
-
- mock.__getitem__ = f
- self.assertFalse(mock.__getitem__ is f)
- self.assertEqual(mock['foo'], (mock, 'fish'))
-
- # When you pull the function back of the *instance*
- # the first argument (self) is removed
- def instance_f(name):
- pass
- self.assertEqual(inspect.getargspec(mock.__getitem__), inspect.getargspec(instance_f))
-
- mock.__getitem__ = mock
- self.assertTrue(mock.__getitem__ is mock)
-
-
- def testRepr(self):
- mock = Mock()
- self.assertEqual(repr(mock), object.__repr__(mock))
- mock.__repr__ = lambda s: 'foo'
- self.assertEqual(repr(mock), 'foo')
-
-
- def testStr(self):
- mock = Mock()
- self.assertEqual(str(mock), object.__str__(mock))
- mock.__str__ = lambda s: 'foo'
- self.assertEqual(str(mock), 'foo')
-
- @unittest2.skipIf(inPy3k, "no unicode in Python 3")
- def testUnicode(self):
- mock = Mock()
- self.assertEqual(unicode(mock), unicode(str(mock)))
-
- mock.__unicode__ = lambda s: unicode('foo')
- self.assertEqual(unicode(mock), unicode('foo'))
-
-
- def testDictMethods(self):
- mock = Mock()
-
- self.assertRaises(TypeError, lambda: mock['foo'])
- def _del():
- del mock['foo']
- def _set():
- mock['foo'] = 3
- self.assertRaises(TypeError, _del)
- self.assertRaises(TypeError, _set)
-
- _dict = {}
- def getitem(s, name):
- return _dict[name]
- def setitem(s, name, value):
- _dict[name] = value
- def delitem(s, name):
- del _dict[name]
-
- mock.__setitem__ = setitem
- mock.__getitem__ = getitem
- mock.__delitem__ = delitem
-
- self.assertRaises(KeyError, lambda: mock['foo'])
- mock['foo'] = 'bar'
- self.assertEqual(_dict, {'foo': 'bar'})
- self.assertEqual(mock['foo'], 'bar')
- del mock['foo']
- self.assertEqual(_dict, {})
-
-
- def testNumeric(self):
- original = mock = Mock()
- mock.value = 0
-
- self.assertRaises(TypeError, lambda: mock + 3)
-
- def add(self, other):
- mock.value += other
- return self
- mock.__add__ = add
- self.assertEqual(mock + 3, mock)
- self.assertEqual(mock.value, 3)
-
- del mock.__add__
- def iadd(mock):
- mock += 3
- self.assertRaises(TypeError, iadd, mock)
- mock.__iadd__ = add
- mock += 6
- self.assertEqual(mock, original)
- self.assertEqual(mock.value, 9)
-
- self.assertRaises(TypeError, lambda: 3 + mock)
- mock.__radd__ = add
- self.assertEqual(7 + mock, mock)
- self.assertEqual(mock.value, 16)
-
-
- def testHash(self):
- mock = Mock()
- # test delegation
- self.assertEqual(hash(mock), Mock.__hash__(mock))
-
- def _hash(s):
- return 3
- mock.__hash__ = _hash
- self.assertEqual(hash(mock), 3)
-
-
- def testNonZero(self):
- m = Mock()
- self.assertTrue(bool(m))
-
- nonzero = lambda s: False
- if not inPy3k:
- m.__nonzero__ = nonzero
- else:
- m.__bool__ = nonzero
-
- self.assertFalse(bool(m))
-
-
- def testComparison(self):
- if not inPy3k:
- # incomparable in Python 3
- self. assertEqual(Mock() < 3, object() < 3)
- self. assertEqual(Mock() > 3, object() > 3)
- self. assertEqual(Mock() <= 3, object() <= 3)
- self. assertEqual(Mock() >= 3, object() >= 3)
-
- mock = Mock()
- def comp(s, o):
- return True
- mock.__lt__ = mock.__gt__ = mock.__le__ = mock.__ge__ = comp
- self. assertTrue(mock < 3)
- self. assertTrue(mock > 3)
- self. assertTrue(mock <= 3)
- self. assertTrue(mock >= 3)
-
-
- def testEquality(self):
- mock = Mock()
- self.assertEqual(mock, mock)
- self.assertNotEqual(mock, Mock())
- self.assertNotEqual(mock, 3)
-
- def eq(self, other):
- return other == 3
- mock.__eq__ = eq
- self.assertTrue(mock == 3)
- self.assertFalse(mock == 4)
-
- def ne(self, other):
- return other == 3
- mock.__ne__ = ne
- self.assertTrue(mock != 3)
- self.assertFalse(mock != 4)
-
-
- def testLenContainsIter(self):
- mock = Mock()
-
- self.assertRaises(TypeError, len, mock)
- self.assertRaises(TypeError, iter, mock)
- self.assertRaises(TypeError, lambda: 'foo' in mock)
-
- mock.__len__ = lambda s: 6
- self.assertEqual(len(mock), 6)
-
- mock.__contains__ = lambda s, o: o == 3
- self.assertTrue(3 in mock)
- self.assertFalse(6 in mock)
-
- mock.__iter__ = lambda s: iter('foobarbaz')
- self.assertEqual(list(mock), list('foobarbaz'))
-
-
- def testMagicMock(self):
- mock = MagicMock()
-
- mock.__iter__.return_value = iter([1, 2, 3])
- self.assertEqual(list(mock), [1, 2, 3])
-
- if inPy3k:
- mock.__bool__.return_value = False
- self.assertFalse(hasattr(mock, '__nonzero__'))
- else:
- mock.__nonzero__.return_value = False
- self.assertFalse(hasattr(mock, '__bool__'))
-
- self.assertFalse(bool(mock))
-
- for entry in _magics:
- self.assertTrue(hasattr(mock, entry))
- self.assertFalse(hasattr(mock, '__imaginery__'))
-
-
- def testMagicMockDefaults(self):
- mock = MagicMock()
- self.assertEqual(int(mock), 0)
- self.assertEqual(complex(mock), 0j)
- self.assertEqual(float(mock), 0.0)
- self.assertEqual(long(mock), long(0))
- self.assertNotIn(object(), mock)
- self.assertEqual(len(mock), 0)
- self.assertEqual(list(mock), [])
- self.assertEqual(hash(mock), object.__hash__(mock))
- self.assertEqual(repr(mock), object.__repr__(mock))
- self.assertEqual(str(mock), object.__str__(mock))
- self.assertEqual(unicode(mock), object.__str__(mock))
- self.assertIsInstance(unicode(mock), unicode)
- self.assertTrue(bool(mock))
- if not inPy3k:
- self.assertEqual(oct(mock), '0')
- else:
- # in Python 3 oct and hex use __index__
- # so these tests are for __index__ in py3k
- self.assertEqual(oct(mock), '0o0')
- self.assertEqual(hex(mock), '0x0')
-
-
- @unittest2.skipIf(inPy3k, "no __cmp__ in Python 3")
- def testNonDefaultMagicMethods(self):
- mock = MagicMock()
- self.assertRaises(AttributeError, lambda: mock.__cmp__)
-
- mock = Mock()
- mock.__cmp__ = lambda s, o: 0
-
- self.assertEqual(mock, object())
-
-
-if __name__ == '__main__':
- unittest2.main()
-
+# Copyright (C) 2007-2010 Michael Foord & the mock team +# E-mail: fuzzyman AT voidspace DOT org DOT uk +# http://www.voidspace.org.uk/python/mock/ + +from tests.support import unittest2, inPy3k + +try: + unicode +except NameError: + # Python 3 + unicode = str + long = int + +import inspect +from mock import Mock, MagicMock, _magics + + + +class TestMockingMagicMethods(unittest2.TestCase): + + def testDeletingMagicMethods(self): + mock = Mock() + self.assertFalse(hasattr(mock, '__getitem__')) + + mock.__getitem__ = Mock() + self.assertTrue(hasattr(mock, '__getitem__')) + + del mock.__getitem__ + self.assertFalse(hasattr(mock, '__getitem__')) + + + def testMagicMethodWrapping(self): + mock = Mock() + def f(self, name): + return self, 'fish' + + mock.__getitem__ = f + self.assertFalse(mock.__getitem__ is f) + self.assertEqual(mock['foo'], (mock, 'fish')) + + # When you pull the function back of the *instance* + # the first argument (self) is removed + def instance_f(name): + pass + self.assertEqual(inspect.getargspec(mock.__getitem__), inspect.getargspec(instance_f)) + + mock.__getitem__ = mock + self.assertTrue(mock.__getitem__ is mock) + + + def testRepr(self): + mock = Mock() + self.assertEqual(repr(mock), object.__repr__(mock)) + mock.__repr__ = lambda s: 'foo' + self.assertEqual(repr(mock), 'foo') + + + def testStr(self): + mock = Mock() + self.assertEqual(str(mock), object.__str__(mock)) + mock.__str__ = lambda s: 'foo' + self.assertEqual(str(mock), 'foo') + + @unittest2.skipIf(inPy3k, "no unicode in Python 3") + def testUnicode(self): + mock = Mock() + self.assertEqual(unicode(mock), unicode(str(mock))) + + mock.__unicode__ = lambda s: unicode('foo') + self.assertEqual(unicode(mock), unicode('foo')) + + + def testDictMethods(self): + mock = Mock() + + self.assertRaises(TypeError, lambda: mock['foo']) + def _del(): + del mock['foo'] + def _set(): + mock['foo'] = 3 + self.assertRaises(TypeError, _del) + self.assertRaises(TypeError, _set) + + _dict = {} + def getitem(s, name): + return _dict[name] + def setitem(s, name, value): + _dict[name] = value + def delitem(s, name): + del _dict[name] + + mock.__setitem__ = setitem + mock.__getitem__ = getitem + mock.__delitem__ = delitem + + self.assertRaises(KeyError, lambda: mock['foo']) + mock['foo'] = 'bar' + self.assertEqual(_dict, {'foo': 'bar'}) + self.assertEqual(mock['foo'], 'bar') + del mock['foo'] + self.assertEqual(_dict, {}) + + + def testNumeric(self): + original = mock = Mock() + mock.value = 0 + + self.assertRaises(TypeError, lambda: mock + 3) + + def add(self, other): + mock.value += other + return self + mock.__add__ = add + self.assertEqual(mock + 3, mock) + self.assertEqual(mock.value, 3) + + del mock.__add__ + def iadd(mock): + mock += 3 + self.assertRaises(TypeError, iadd, mock) + mock.__iadd__ = add + mock += 6 + self.assertEqual(mock, original) + self.assertEqual(mock.value, 9) + + self.assertRaises(TypeError, lambda: 3 + mock) + mock.__radd__ = add + self.assertEqual(7 + mock, mock) + self.assertEqual(mock.value, 16) + + + def testHash(self): + mock = Mock() + # test delegation + self.assertEqual(hash(mock), Mock.__hash__(mock)) + + def _hash(s): + return 3 + mock.__hash__ = _hash + self.assertEqual(hash(mock), 3) + + + def testNonZero(self): + m = Mock() + self.assertTrue(bool(m)) + + nonzero = lambda s: False + if not inPy3k: + m.__nonzero__ = nonzero + else: + m.__bool__ = nonzero + + self.assertFalse(bool(m)) + + + def testComparison(self): + if not inPy3k: + # incomparable in Python 3 + self. assertEqual(Mock() < 3, object() < 3) + self. assertEqual(Mock() > 3, object() > 3) + self. assertEqual(Mock() <= 3, object() <= 3) + self. assertEqual(Mock() >= 3, object() >= 3) + + mock = Mock() + def comp(s, o): + return True + mock.__lt__ = mock.__gt__ = mock.__le__ = mock.__ge__ = comp + self. assertTrue(mock < 3) + self. assertTrue(mock > 3) + self. assertTrue(mock <= 3) + self. assertTrue(mock >= 3) + + + def testEquality(self): + mock = Mock() + self.assertEqual(mock, mock) + self.assertNotEqual(mock, Mock()) + self.assertNotEqual(mock, 3) + + def eq(self, other): + return other == 3 + mock.__eq__ = eq + self.assertTrue(mock == 3) + self.assertFalse(mock == 4) + + def ne(self, other): + return other == 3 + mock.__ne__ = ne + self.assertTrue(mock != 3) + self.assertFalse(mock != 4) + + + def testLenContainsIter(self): + mock = Mock() + + self.assertRaises(TypeError, len, mock) + self.assertRaises(TypeError, iter, mock) + self.assertRaises(TypeError, lambda: 'foo' in mock) + + mock.__len__ = lambda s: 6 + self.assertEqual(len(mock), 6) + + mock.__contains__ = lambda s, o: o == 3 + self.assertTrue(3 in mock) + self.assertFalse(6 in mock) + + mock.__iter__ = lambda s: iter('foobarbaz') + self.assertEqual(list(mock), list('foobarbaz')) + + + def testMagicMock(self): + mock = MagicMock() + + mock.__iter__.return_value = iter([1, 2, 3]) + self.assertEqual(list(mock), [1, 2, 3]) + + if inPy3k: + mock.__bool__.return_value = False + self.assertFalse(hasattr(mock, '__nonzero__')) + else: + mock.__nonzero__.return_value = False + self.assertFalse(hasattr(mock, '__bool__')) + + self.assertFalse(bool(mock)) + + for entry in _magics: + self.assertTrue(hasattr(mock, entry)) + self.assertFalse(hasattr(mock, '__imaginery__')) + + + def testMagicMockDefaults(self): + mock = MagicMock() + self.assertEqual(int(mock), 0) + self.assertEqual(complex(mock), 0j) + self.assertEqual(float(mock), 0.0) + self.assertEqual(long(mock), long(0)) + self.assertNotIn(object(), mock) + self.assertEqual(len(mock), 0) + self.assertEqual(list(mock), []) + self.assertEqual(hash(mock), object.__hash__(mock)) + self.assertEqual(repr(mock), object.__repr__(mock)) + self.assertEqual(str(mock), object.__str__(mock)) + self.assertEqual(unicode(mock), object.__str__(mock)) + self.assertIsInstance(unicode(mock), unicode) + self.assertTrue(bool(mock)) + if not inPy3k: + self.assertEqual(oct(mock), '0') + else: + # in Python 3 oct and hex use __index__ + # so these tests are for __index__ in py3k + self.assertEqual(oct(mock), '0o0') + self.assertEqual(hex(mock), '0x0') + + + @unittest2.skipIf(inPy3k, "no __cmp__ in Python 3") + def testNonDefaultMagicMethods(self): + mock = MagicMock() + self.assertRaises(AttributeError, lambda: mock.__cmp__) + + mock = Mock() + mock.__cmp__ = lambda s, o: 0 + + self.assertEqual(mock, object()) + + +if __name__ == '__main__': + unittest2.main() diff --git a/tests/testmock.py b/tests/testmock.py index ec12bba..e0e3743 100644 --- a/tests/testmock.py +++ b/tests/testmock.py @@ -1,307 +1,306 @@ -# Copyright (C) 2007-2010 Michael Foord & the mock team
-# E-mail: fuzzyman AT voidspace DOT org DOT uk
-# http://www.voidspace.org.uk/python/mock/
-
-from tests.support import unittest2
-
-from mock import Mock, sentinel, DEFAULT
-
-try:
- unicode
-except NameError:
- unicode = str
-
-
-class MockTest(unittest2.TestCase):
-
- def testAll(self):
- # if __all__ is badly defined then import * will raise an error
- # We have to exec it because you can't import * inside a method
- # in Python 3
- exec("from mock import *")
-
- def testConstructor(self):
- mock = Mock()
-
- self.assertFalse(mock.called, "called not initialised correctly")
- self.assertEqual(mock.call_count, 0, "call_count not initialised correctly")
- self.assertTrue(isinstance(mock.return_value, Mock), "return_value not initialised correctly")
-
- self.assertEqual(mock.call_args, None, "call_args not initialised correctly")
- self.assertEqual(mock.call_args_list, [], "call_args_list not initialised correctly")
- self.assertEqual(mock.method_calls, [],
- "method_calls not initialised correctly")
-
- # Can't use hasattr for this test as it always returns True on a mock...
- self.assertFalse('_items' in mock.__dict__, "default mock should not have '_items' attribute")
-
- self.assertIsNone(mock._parent, "parent not initialised correctly")
- self.assertIsNone(mock._methods, "methods not initialised correctly")
- self.assertEqual(mock._children, {}, "children not initialised incorrectly")
-
- def testUnicodeNotBroken(self):
- # This used to raise an exception with Python 2.5 and Mock 0.4
- unicode(Mock())
-
- def testReturnValueInConstructor(self):
- mock = Mock(return_value=None)
- self.assertIsNone(mock.return_value, "return value in constructor not honoured")
-
-
- def testSideEffect(self):
- mock = Mock()
-
- def effect(*args, **kwargs):
- raise SystemError('kablooie')
-
- mock.side_effect = effect
- self.assertRaises(SystemError, mock, 1, 2, fish=3)
- mock.assert_called_with(1, 2, fish=3)
-
- results = [1, 2, 3]
- def effect():
- return results.pop()
- mock.side_effect = effect
-
- self.assertEqual([mock(), mock(), mock()], [3, 2, 1],
- "side effect not used correctly")
-
- mock = Mock(side_effect=sentinel.SideEffect)
- self.assertEqual(mock.side_effect, sentinel.SideEffect,
- "side effect in constructor not used")
-
- def side_effect():
- return DEFAULT
- mock = Mock(side_effect=side_effect, return_value=sentinel.RETURN)
- self.assertEqual(mock(), sentinel.RETURN)
-
-
- def testReset(self):
- parent = Mock()
- spec = ["something"]
- mock = Mock(name="child", parent=parent, spec=spec)
- mock(sentinel.Something, something=sentinel.SomethingElse)
- something = mock.something
- mock.something()
- mock.side_effect = sentinel.SideEffect
- return_value = mock.return_value
- return_value()
-
- mock.reset_mock()
-
- self.assertEqual(mock._name, "child", "name incorrectly reset")
- self.assertEqual(mock._parent, parent, "parent incorrectly reset")
- self.assertEqual(mock._methods, spec, "methods incorrectly reset")
-
- self.assertFalse(mock.called, "called not reset")
- self.assertEqual(mock.call_count, 0, "call_count not reset")
- self.assertEqual(mock.call_args, None, "call_args not reset")
- self.assertEqual(mock.call_args_list, [], "call_args_list not reset")
- self.assertEqual(mock.method_calls, [],
- "method_calls not initialised correctly: %r != %r" % (mock.method_calls, []))
-
- self.assertEqual(mock.side_effect, sentinel.SideEffect,
- "side_effect incorrectly reset")
- self.assertEqual(mock.return_value, return_value,
- "return_value incorrectly reset")
- self.assertFalse(return_value.called, "return value mock not reset")
- self.assertEqual(mock._children, {'something': something},
- "children reset incorrectly")
- self.assertEqual(mock.something, something,
- "children incorrectly cleared")
- self.assertFalse(mock.something.called, "child not reset")
-
-
- def testCall(self):
- mock = Mock()
- self.assertTrue(isinstance(mock.return_value, Mock), "Default return_value should be a Mock")
-
- result = mock()
- self.assertEqual(mock(), result, "different result from consecutive calls")
- mock.reset_mock()
-
- ret_val = mock(sentinel.Arg)
- self.assertTrue(mock.called, "called not set")
- self.assertEqual(mock.call_count, 1, "call_count incoreect")
- self.assertEqual(mock.call_args, ((sentinel.Arg,), {}), "call_args not set")
- self.assertEqual(mock.call_args_list, [((sentinel.Arg,), {})], "call_args_list not initialised correctly")
-
- mock.return_value = sentinel.ReturnValue
- ret_val = mock(sentinel.Arg, key=sentinel.KeyArg)
- self.assertEqual(ret_val, sentinel.ReturnValue, "incorrect return value")
-
- self.assertEqual(mock.call_count, 2, "call_count incorrect")
- self.assertEqual(mock.call_args, ((sentinel.Arg,), {'key': sentinel.KeyArg}), "call_args not set")
- self.assertEqual(mock.call_args_list, [((sentinel.Arg,), {}), ((sentinel.Arg,), {'key': sentinel.KeyArg})], "call_args_list not set")
-
- def testCallArgsComparison(self):
- mock = Mock()
- mock()
- mock(sentinel.Arg)
- mock(kw=sentinel.Kwarg)
- mock(sentinel.Arg, kw=sentinel.Kwarg)
- self.assertEqual(mock.call_args_list, [(),
- ((sentinel.Arg,),),
- ({"kw": sentinel.Kwarg},),
- ((sentinel.Arg,), {"kw": sentinel.Kwarg})])
- self.assertEqual(mock.call_args, ((sentinel.Arg,), {"kw": sentinel.Kwarg}))
-
- def testAssertCalledWith(self):
- mock = Mock()
- mock()
-
- # Will raise an exception if it fails
- mock.assert_called_with()
- self.assertRaises(AssertionError, mock.assert_called_with, 1)
-
- mock.reset_mock()
- self.assertRaises(AssertionError, mock.assert_called_with)
-
- mock(1, 2, 3, a='fish', b='nothing')
- mock.assert_called_with(1, 2, 3, a='fish', b='nothing')
-
-
- def testAttributeAccessReturnsMocks(self):
- mock = Mock()
- something = mock.something
- self.assertTrue(isinstance(something, Mock), "attribute isn't a mock")
- self.assertEqual(mock.something, something, "different attributes returned for same name")
-
- # Usage example
- mock = Mock()
- mock.something.return_value = 3
-
- self.assertEqual(mock.something(), 3, "method returned wrong value")
- self.assertTrue(mock.something.called, "method didn't record being called")
-
-
- def testAttributesHaveNameAndParentSet(self):
- mock = Mock()
- something = mock.something
-
- self.assertEqual(something._name, "something", "attribute name not set correctly")
- self.assertEqual(something._parent, mock, "attribute parent not set correctly")
-
-
- def testMethodCallsRecorded(self):
- mock = Mock()
- mock.something(3, fish=None)
- mock.something_else.something(6, cake=sentinel.Cake)
-
- self.assertEqual(mock.something_else.method_calls,
- [("something", (6,), {'cake': sentinel.Cake})],
- "method calls not recorded correctly")
- self.assertEqual(mock.method_calls,
- [("something", (3,), {'fish': None}),
- ("something_else.something", (6,), {'cake': sentinel.Cake})],
- "method calls not recorded correctly")
-
- def testMethodCallsCompareEasily(self):
- mock = Mock()
- mock.something()
- self.assertEqual(mock.method_calls, [('something',)])
- self.assertEqual(mock.method_calls, [('something', (), {})])
-
- mock = Mock()
- mock.something('different')
- self.assertEqual(mock.method_calls, [('something', ('different',))])
- self.assertEqual(mock.method_calls, [('something', ('different',), {})])
-
- mock = Mock()
- mock.something(x=1)
- self.assertEqual(mock.method_calls, [('something', {'x': 1})])
- self.assertEqual(mock.method_calls, [('something', (), {'x': 1})])
-
- mock = Mock()
- mock.something('different', some='more')
- self.assertEqual(mock.method_calls, [('something', ('different',), {'some': 'more'})])
-
- def testOnlyAllowedMethodsExist(self):
- spec = ["something"]
- mock = Mock(spec=spec)
-
- # this should be allowed
- mock.something
- self.assertRaisesRegexp(AttributeError,
- "Mock object has no attribute 'something_else'",
- lambda: mock.something_else)
-
-
- def testFromSpec(self):
- class Something(object):
- x = 3
- __something__ = None
- def y(self):
- pass
-
- def testAttributes(mock):
- # should work
- mock.x
- mock.y
- self.assertRaisesRegexp(AttributeError,
- "Mock object has no attribute 'z'",
- lambda: mock.z)
- self.assertRaisesRegexp(AttributeError,
- "Mock object has no attribute '__something__'",
- lambda: mock.__something__)
-
- testAttributes(Mock(spec=Something))
- testAttributes(Mock(spec=Something()))
-
-
- def testWrapsCalls(self):
- real = Mock()
-
- mock = Mock(wraps=real)
- self.assertEqual(mock(), real())
-
- real.reset_mock()
-
- mock(1, 2, fish=3)
- real.assert_called_with(1, 2, fish=3)
-
-
- def testWrapsCallWithNonDefaultReturnValue(self):
- real = Mock()
-
- mock = Mock(wraps=real)
- mock.return_value = 3
-
- self.assertEqual(mock(), 3)
- self.assertFalse(real.called)
-
-
- def testWrapsAttributes(self):
- class Real(object):
- attribute = Mock()
-
- real = Real()
-
- mock = Mock(wraps=real)
- self.assertEqual(mock.attribute(), real.attribute())
- self.assertRaises(AttributeError, lambda: mock.fish)
-
- self.assertNotEqual(mock.attribute, real.attribute)
- result = mock.attribute.frog(1, 2, fish=3)
- Real.attribute.frog.assert_called_with(1, 2, fish=3)
- self.assertEqual(result, Real.attribute.frog())
-
-
- def testExceptionalSideEffect(self):
- mock = Mock(side_effect=AttributeError)
- self.assertRaises(AttributeError, mock)
-
- mock = Mock(side_effect=AttributeError('foo'))
- self.assertRaises(AttributeError, mock)
-
- def testBaseExceptionalSideEffect(self):
- mock = Mock(side_effect=KeyboardInterrupt)
- self.assertRaises(KeyboardInterrupt, mock)
-
- mock = Mock(side_effect=KeyboardInterrupt('foo'))
- self.assertRaises(KeyboardInterrupt, mock)
-
-
-if __name__ == '__main__':
- unittest2.main()
-
+# Copyright (C) 2007-2010 Michael Foord & the mock team +# E-mail: fuzzyman AT voidspace DOT org DOT uk +# http://www.voidspace.org.uk/python/mock/ + +from tests.support import unittest2 + +from mock import Mock, sentinel, DEFAULT + +try: + unicode +except NameError: + unicode = str + + +class MockTest(unittest2.TestCase): + + def testAll(self): + # if __all__ is badly defined then import * will raise an error + # We have to exec it because you can't import * inside a method + # in Python 3 + exec("from mock import *") + + def testConstructor(self): + mock = Mock() + + self.assertFalse(mock.called, "called not initialised correctly") + self.assertEqual(mock.call_count, 0, "call_count not initialised correctly") + self.assertTrue(isinstance(mock.return_value, Mock), "return_value not initialised correctly") + + self.assertEqual(mock.call_args, None, "call_args not initialised correctly") + self.assertEqual(mock.call_args_list, [], "call_args_list not initialised correctly") + self.assertEqual(mock.method_calls, [], + "method_calls not initialised correctly") + + # Can't use hasattr for this test as it always returns True on a mock... + self.assertFalse('_items' in mock.__dict__, "default mock should not have '_items' attribute") + + self.assertIsNone(mock._parent, "parent not initialised correctly") + self.assertIsNone(mock._methods, "methods not initialised correctly") + self.assertEqual(mock._children, {}, "children not initialised incorrectly") + + def testUnicodeNotBroken(self): + # This used to raise an exception with Python 2.5 and Mock 0.4 + unicode(Mock()) + + def testReturnValueInConstructor(self): + mock = Mock(return_value=None) + self.assertIsNone(mock.return_value, "return value in constructor not honoured") + + + def testSideEffect(self): + mock = Mock() + + def effect(*args, **kwargs): + raise SystemError('kablooie') + + mock.side_effect = effect + self.assertRaises(SystemError, mock, 1, 2, fish=3) + mock.assert_called_with(1, 2, fish=3) + + results = [1, 2, 3] + def effect(): + return results.pop() + mock.side_effect = effect + + self.assertEqual([mock(), mock(), mock()], [3, 2, 1], + "side effect not used correctly") + + mock = Mock(side_effect=sentinel.SideEffect) + self.assertEqual(mock.side_effect, sentinel.SideEffect, + "side effect in constructor not used") + + def side_effect(): + return DEFAULT + mock = Mock(side_effect=side_effect, return_value=sentinel.RETURN) + self.assertEqual(mock(), sentinel.RETURN) + + + def testReset(self): + parent = Mock() + spec = ["something"] + mock = Mock(name="child", parent=parent, spec=spec) + mock(sentinel.Something, something=sentinel.SomethingElse) + something = mock.something + mock.something() + mock.side_effect = sentinel.SideEffect + return_value = mock.return_value + return_value() + + mock.reset_mock() + + self.assertEqual(mock._name, "child", "name incorrectly reset") + self.assertEqual(mock._parent, parent, "parent incorrectly reset") + self.assertEqual(mock._methods, spec, "methods incorrectly reset") + + self.assertFalse(mock.called, "called not reset") + self.assertEqual(mock.call_count, 0, "call_count not reset") + self.assertEqual(mock.call_args, None, "call_args not reset") + self.assertEqual(mock.call_args_list, [], "call_args_list not reset") + self.assertEqual(mock.method_calls, [], + "method_calls not initialised correctly: %r != %r" % (mock.method_calls, [])) + + self.assertEqual(mock.side_effect, sentinel.SideEffect, + "side_effect incorrectly reset") + self.assertEqual(mock.return_value, return_value, + "return_value incorrectly reset") + self.assertFalse(return_value.called, "return value mock not reset") + self.assertEqual(mock._children, {'something': something}, + "children reset incorrectly") + self.assertEqual(mock.something, something, + "children incorrectly cleared") + self.assertFalse(mock.something.called, "child not reset") + + + def testCall(self): + mock = Mock() + self.assertTrue(isinstance(mock.return_value, Mock), "Default return_value should be a Mock") + + result = mock() + self.assertEqual(mock(), result, "different result from consecutive calls") + mock.reset_mock() + + ret_val = mock(sentinel.Arg) + self.assertTrue(mock.called, "called not set") + self.assertEqual(mock.call_count, 1, "call_count incoreect") + self.assertEqual(mock.call_args, ((sentinel.Arg,), {}), "call_args not set") + self.assertEqual(mock.call_args_list, [((sentinel.Arg,), {})], "call_args_list not initialised correctly") + + mock.return_value = sentinel.ReturnValue + ret_val = mock(sentinel.Arg, key=sentinel.KeyArg) + self.assertEqual(ret_val, sentinel.ReturnValue, "incorrect return value") + + self.assertEqual(mock.call_count, 2, "call_count incorrect") + self.assertEqual(mock.call_args, ((sentinel.Arg,), {'key': sentinel.KeyArg}), "call_args not set") + self.assertEqual(mock.call_args_list, [((sentinel.Arg,), {}), ((sentinel.Arg,), {'key': sentinel.KeyArg})], "call_args_list not set") + + def testCallArgsComparison(self): + mock = Mock() + mock() + mock(sentinel.Arg) + mock(kw=sentinel.Kwarg) + mock(sentinel.Arg, kw=sentinel.Kwarg) + self.assertEqual(mock.call_args_list, [(), + ((sentinel.Arg,),), + ({"kw": sentinel.Kwarg},), + ((sentinel.Arg,), {"kw": sentinel.Kwarg})]) + self.assertEqual(mock.call_args, ((sentinel.Arg,), {"kw": sentinel.Kwarg})) + + def testAssertCalledWith(self): + mock = Mock() + mock() + + # Will raise an exception if it fails + mock.assert_called_with() + self.assertRaises(AssertionError, mock.assert_called_with, 1) + + mock.reset_mock() + self.assertRaises(AssertionError, mock.assert_called_with) + + mock(1, 2, 3, a='fish', b='nothing') + mock.assert_called_with(1, 2, 3, a='fish', b='nothing') + + + def testAttributeAccessReturnsMocks(self): + mock = Mock() + something = mock.something + self.assertTrue(isinstance(something, Mock), "attribute isn't a mock") + self.assertEqual(mock.something, something, "different attributes returned for same name") + + # Usage example + mock = Mock() + mock.something.return_value = 3 + + self.assertEqual(mock.something(), 3, "method returned wrong value") + self.assertTrue(mock.something.called, "method didn't record being called") + + + def testAttributesHaveNameAndParentSet(self): + mock = Mock() + something = mock.something + + self.assertEqual(something._name, "something", "attribute name not set correctly") + self.assertEqual(something._parent, mock, "attribute parent not set correctly") + + + def testMethodCallsRecorded(self): + mock = Mock() + mock.something(3, fish=None) + mock.something_else.something(6, cake=sentinel.Cake) + + self.assertEqual(mock.something_else.method_calls, + [("something", (6,), {'cake': sentinel.Cake})], + "method calls not recorded correctly") + self.assertEqual(mock.method_calls, + [("something", (3,), {'fish': None}), + ("something_else.something", (6,), {'cake': sentinel.Cake})], + "method calls not recorded correctly") + + def testMethodCallsCompareEasily(self): + mock = Mock() + mock.something() + self.assertEqual(mock.method_calls, [('something',)]) + self.assertEqual(mock.method_calls, [('something', (), {})]) + + mock = Mock() + mock.something('different') + self.assertEqual(mock.method_calls, [('something', ('different',))]) + self.assertEqual(mock.method_calls, [('something', ('different',), {})]) + + mock = Mock() + mock.something(x=1) + self.assertEqual(mock.method_calls, [('something', {'x': 1})]) + self.assertEqual(mock.method_calls, [('something', (), {'x': 1})]) + + mock = Mock() + mock.something('different', some='more') + self.assertEqual(mock.method_calls, [('something', ('different',), {'some': 'more'})]) + + def testOnlyAllowedMethodsExist(self): + spec = ["something"] + mock = Mock(spec=spec) + + # this should be allowed + mock.something + self.assertRaisesRegexp(AttributeError, + "Mock object has no attribute 'something_else'", + lambda: mock.something_else) + + + def testFromSpec(self): + class Something(object): + x = 3 + __something__ = None + def y(self): + pass + + def testAttributes(mock): + # should work + mock.x + mock.y + self.assertRaisesRegexp(AttributeError, + "Mock object has no attribute 'z'", + lambda: mock.z) + self.assertRaisesRegexp(AttributeError, + "Mock object has no attribute '__something__'", + lambda: mock.__something__) + + testAttributes(Mock(spec=Something)) + testAttributes(Mock(spec=Something())) + + + def testWrapsCalls(self): + real = Mock() + + mock = Mock(wraps=real) + self.assertEqual(mock(), real()) + + real.reset_mock() + + mock(1, 2, fish=3) + real.assert_called_with(1, 2, fish=3) + + + def testWrapsCallWithNonDefaultReturnValue(self): + real = Mock() + + mock = Mock(wraps=real) + mock.return_value = 3 + + self.assertEqual(mock(), 3) + self.assertFalse(real.called) + + + def testWrapsAttributes(self): + class Real(object): + attribute = Mock() + + real = Real() + + mock = Mock(wraps=real) + self.assertEqual(mock.attribute(), real.attribute()) + self.assertRaises(AttributeError, lambda: mock.fish) + + self.assertNotEqual(mock.attribute, real.attribute) + result = mock.attribute.frog(1, 2, fish=3) + Real.attribute.frog.assert_called_with(1, 2, fish=3) + self.assertEqual(result, Real.attribute.frog()) + + + def testExceptionalSideEffect(self): + mock = Mock(side_effect=AttributeError) + self.assertRaises(AttributeError, mock) + + mock = Mock(side_effect=AttributeError('foo')) + self.assertRaises(AttributeError, mock) + + def testBaseExceptionalSideEffect(self): + mock = Mock(side_effect=KeyboardInterrupt) + self.assertRaises(KeyboardInterrupt, mock) + + mock = Mock(side_effect=KeyboardInterrupt('foo')) + self.assertRaises(KeyboardInterrupt, mock) + + +if __name__ == '__main__': + unittest2.main() diff --git a/tests/testmocksignature.py b/tests/testmocksignature.py index d4fb7ac..e2a7850 100644 --- a/tests/testmocksignature.py +++ b/tests/testmocksignature.py @@ -16,34 +16,34 @@ class TestMockSignature(unittest2.TestCase): def f(a): pass mock = Mock() - + f2 = mocksignature(f, mock) self.assertIs(f2.mock, mock) - + self.assertRaises(TypeError, f2) mock.return_value = 3 self.assertEqual(f2('foo'), 3) mock.assert_called_with('foo') f2.mock.assert_called_with('foo') - + def testFunctionWithoutExplicitMock(self): def f(a): pass - + f2 = mocksignature(f) self.assertIsInstance(f2.mock, Mock) - + self.assertRaises(TypeError, f2) f2.mock.return_value = 3 self.assertEqual(f2('foo'), 3) f2.mock.assert_called_with('foo') - - + + def testMethod(self): class Foo(object): def method(self, a, b): pass - + f = Foo() mock = Mock() mock.return_value = 3 @@ -60,67 +60,67 @@ class TestMockSignature(unittest2.TestCase): f2(3) mock.assert_called_with(3, None) mock.reset_mock() - + f2(1, 7) mock.assert_called_with(1, 7) mock.reset_mock() - + f2(b=1, a=7) mock.assert_called_with(7, 1) mock.reset_mock() - + a = object() def f(a=a): pass f2 = mocksignature(f, mock) f2() mock.assert_called_with(a) - + def testIntrospection(self): def f(a, *args, **kwargs): pass f2 = mocksignature(f, f) self.assertEqual(inspect.getargspec(f), inspect.getargspec(f2)) - + def f(a, b=None, c=3, d=object()): pass f2 = mocksignature(f, f) self.assertEqual(inspect.getargspec(f), inspect.getargspec(f2)) - - + + def testFunctionWithVarArgsAndKwargs(self): def f(a, b=None, *args, **kwargs): return (a, b, args, kwargs) f2 = mocksignature(f, f) self.assertEqual(f2(3, 4, 5, x=6, y=9), (3, 4, (5,), {'x': 6, 'y': 9})) self.assertEqual(f2(3, x=6, y=9, b='a'), (3, 'a', (), {'x': 6, 'y': 9})) - - + + def testMockSignatureWithPatch(self): mock = Mock() - + def f(a, b, c): pass mock.f = f - + @apply @patch.object(mock, 'f', mocksignature=True) def test(mock_f): self.assertRaises(TypeError, mock.f, 3, 4) self.assertRaises(TypeError, mock.f, 3, 4, 5, 6) mock.f(1, 2, 3) - + mock_f.assert_called_with(1, 2, 3) mock.f.mock.assert_called_with(1, 2, 3) - + @apply @patch('tests.support.SomeClass.wibble', mocksignature=True) def test(mock_wibble): from tests.support import SomeClass - + instance = SomeClass() self.assertRaises(TypeError, instance.wibble, 1) instance.wibble() - + mock_wibble.assert_called_with(instance) - instance.wibble.mock.assert_called_with(instance) + instance.wibble.mock.assert_called_with(instance)
\ No newline at end of file diff --git a/tests/testpatch.py b/tests/testpatch.py index 258c0a9..048d621 100644 --- a/tests/testpatch.py +++ b/tests/testpatch.py @@ -1,603 +1,602 @@ -# Copyright (C) 2007-2010 Michael Foord & the mock team
-# E-mail: fuzzyman AT voidspace DOT org DOT uk
-# http://www.voidspace.org.uk/python/mock/
-
-import os
-import warnings
-
-from tests.support import unittest2, apply, inPy3k, SomeClass, with_available
-
-if with_available:
- from tests.support_with import examine_warnings
-
-from mock import Mock, patch, patch_object, sentinel
-
-if not inPy3k:
- builtin_string = '__builtin__'
-else:
- builtin_string = 'builtins'
-
-
-# for use in the test
-something = sentinel.Something
-something_else = sentinel.SomethingElse
-
-
-class Container(object):
- def __init__(self):
- self.values = {}
-
- def __getitem__(self, name):
- return self.values[name]
-
- def __setitem__(self, name, value):
- self.values[name] = value
-
- def __delitem__(self, name):
- del self.values[name]
-
- def __iter__(self):
- return iter(self.values)
-
-
-class PatchTest(unittest2.TestCase):
-
- def testSinglePatchObject(self):
- class Something(object):
- attribute = sentinel.Original
-
- @apply
- @patch.object(Something, 'attribute', sentinel.Patched)
- def test():
- self.assertEqual(Something.attribute, sentinel.Patched, "unpatched")
-
- self.assertEqual(Something.attribute, sentinel.Original, "patch not restored")
-
-
- def testPatchObjectWithNone(self):
- class Something(object):
- attribute = sentinel.Original
-
- @apply
- @patch.object(Something, 'attribute', None)
- def test():
- self.assertIsNone(Something.attribute, "unpatched")
-
- self.assertEqual(Something.attribute, sentinel.Original, "patch not restored")
-
-
- def testMultiplePatchObject(self):
- class Something(object):
- attribute = sentinel.Original
- next_attribute = sentinel.Original2
-
- @apply
- @patch.object(Something, 'attribute', sentinel.Patched)
- @patch.object(Something, 'next_attribute', sentinel.Patched2)
- def test():
- self.assertEqual(Something.attribute, sentinel.Patched, "unpatched")
- self.assertEqual(Something.next_attribute, sentinel.Patched2, "unpatched")
-
- self.assertEqual(Something.attribute, sentinel.Original, "patch not restored")
- self.assertEqual(Something.next_attribute, sentinel.Original2, "patch not restored")
-
-
- def testObjectLookupIsQuiteLazy(self):
- global something
- original = something
- @patch('tests.testpatch.something', sentinel.Something2)
- def test():
- pass
-
- try:
- something = sentinel.replacement_value
- test()
- self.assertEqual(something, sentinel.replacement_value)
- finally:
- something = original
-
-
- def testPatch(self):
- import __main__
- __main__.something = sentinel.Something
-
- @apply
- @patch('__main__.something', sentinel.Something2)
- def test():
- self.assertEqual(__main__.something, sentinel.Something2, "unpatched")
-
- self.assertEqual(__main__.something, sentinel.Something, "patch not restored")
-
- import tests.testpatch as PTModule
-
- @patch('tests.testpatch.something', sentinel.Something2)
- @patch('tests.testpatch.something_else', sentinel.SomethingElse)
- def test():
- self.assertEqual(PTModule.something, sentinel.Something2, "unpatched")
- self.assertEqual(PTModule.something_else, sentinel.SomethingElse, "unpatched")
-
- self.assertEqual(PTModule.something, sentinel.Something, "patch not restored")
- self.assertEqual(PTModule.something_else, sentinel.SomethingElse, "patch not restored")
-
- # Test the patching and restoring works a second time
- test()
-
- self.assertEqual(PTModule.something, sentinel.Something, "patch not restored")
- self.assertEqual(PTModule.something_else, sentinel.SomethingElse, "patch not restored")
-
- mock = Mock()
- mock.return_value = sentinel.Handle
- @patch('%s.open' % builtin_string, mock)
- def test():
- self.assertEqual(open('filename', 'r'), sentinel.Handle, "open not patched")
- test()
- test()
-
- self.assertNotEquals(open, mock, "patch not restored")
-
-
- def testPatchClassAttribute(self):
- import tests.testpatch as PTModule
-
- @patch('tests.testpatch.SomeClass.class_attribute', sentinel.ClassAttribute)
- def test():
- self.assertEqual(PTModule.SomeClass.class_attribute, sentinel.ClassAttribute, "unpatched")
- test()
-
- self.assertIsNone(PTModule.SomeClass.class_attribute, "patch not restored")
-
-
- def testPatchObjectWithDefaultMock(self):
- class Test(object):
- something = sentinel.Original
- something2 = sentinel.Original2
-
- @apply
- @patch.object(Test, 'something')
- def test(mock):
- self.assertEqual(mock, Test.something, "Mock not passed into test function")
- self.assertTrue(isinstance(mock, Mock),
- "patch with two arguments did not create a mock")
-
- @patch.object(Test, 'something')
- @patch.object(Test, 'something2')
- def test(this1, this2, mock1, mock2):
- self.assertEqual(this1, sentinel.this1, "Patched function didn't receive initial argument")
- self.assertEqual(this2, sentinel.this2, "Patched function didn't receive second argument")
- self.assertEqual(mock1, Test.something2, "Mock not passed into test function")
- self.assertEqual(mock2, Test.something, "Second Mock not passed into test function")
- self.assertTrue(isinstance(mock2, Mock),
- "patch with two arguments did not create a mock")
- self.assertTrue(isinstance(mock2, Mock),
- "patch with two arguments did not create a mock")
-
-
- # A hack to test that new mocks are passed the second time
- self.assertNotEquals(outerMock1, mock1, "unexpected value for mock1")
- self.assertNotEquals(outerMock2, mock2, "unexpected value for mock1")
- return mock1, mock2
-
- outerMock1 = None
- outerMock2 = None
- outerMock1, outerMock2 = test(sentinel.this1, sentinel.this2)
-
- # Test that executing a second time creates new mocks
- test(sentinel.this1, sentinel.this2)
-
-
- def testPatchWithSpec(self):
- @patch('tests.testpatch.SomeClass', spec=SomeClass)
- def test(MockSomeClass):
- self.assertEqual(SomeClass, MockSomeClass)
- self.assertTrue(isinstance(SomeClass.wibble, Mock))
- self.assertRaises(AttributeError, lambda: SomeClass.not_wibble)
-
- test()
-
-
- def testPatchObjectWithSpec(self):
- @patch.object(SomeClass, 'class_attribute', spec=SomeClass)
- def test(MockAttribute):
- self.assertEqual(SomeClass.class_attribute, MockAttribute)
- self.assertTrue(isinstance(SomeClass.class_attribute.wibble, Mock))
- self.assertRaises(AttributeError, lambda: SomeClass.class_attribute.not_wibble)
-
- test()
-
-
- def testPatchWithSpecAsList(self):
- @patch('tests.testpatch.SomeClass', spec=['wibble'])
- def test(MockSomeClass):
- self.assertEqual(SomeClass, MockSomeClass)
- self.assertTrue(isinstance(SomeClass.wibble, Mock))
- self.assertRaises(AttributeError, lambda: SomeClass.not_wibble)
-
- test()
-
-
- def testPatchObjectWithSpecAsList(self):
- @patch.object(SomeClass, 'class_attribute', spec=['wibble'])
- def test(MockAttribute):
- self.assertEqual(SomeClass.class_attribute, MockAttribute)
- self.assertTrue(isinstance(SomeClass.class_attribute.wibble, Mock))
- self.assertRaises(AttributeError, lambda: SomeClass.class_attribute.not_wibble)
-
- test()
-
-
- def testNestedPatchWithSpecAsList(self):
- # regression test for nested decorators
- @patch('%s.open' % builtin_string)
- @patch('tests.testpatch.SomeClass', spec=['wibble'])
- def test(MockSomeClass, MockOpen):
- self.assertEqual(SomeClass, MockSomeClass)
- self.assertTrue(isinstance(SomeClass.wibble, Mock))
- self.assertRaises(AttributeError, lambda: SomeClass.not_wibble)
-
-
- def testPatchWithSpecAsBoolean(self):
- @apply
- @patch('tests.testpatch.SomeClass', spec=True)
- def test(MockSomeClass):
- self.assertEqual(SomeClass, MockSomeClass)
- # Should not raise attribute error
- MockSomeClass.wibble
-
- self.assertRaises(AttributeError, lambda: MockSomeClass.not_wibble)
-
-
- def testPatchObjectWithSpecAsBoolean(self):
- from tests import testpatch
- @apply
- @patch.object(testpatch, 'SomeClass', spec=True)
- def test(MockSomeClass):
- self.assertEqual(SomeClass, MockSomeClass)
- # Should not raise attribute error
- MockSomeClass.wibble
-
- self.assertRaises(AttributeError, lambda: MockSomeClass.not_wibble)
-
-
- def testPatchClassActsWithSpecIsInherited(self):
- @apply
- @patch('tests.testpatch.SomeClass', spec=True)
- def test(MockSomeClass):
- instance = MockSomeClass()
- # Should not raise attribute error
- instance.wibble
-
- self.assertRaises(AttributeError, lambda: instance.not_wibble)
-
-
- def testPatchWithCreateMocksNonExistentAttributes(self):
- @patch('%s.frooble' % builtin_string, sentinel.Frooble, create=True)
- def test():
- self.assertEqual(frooble, sentinel.Frooble)
-
- test()
- self.assertRaises(NameError, lambda: frooble)
-
-
- def testPatchObjectWithCreateMocksNonExistentAttributes(self):
- @patch.object(SomeClass, 'frooble', sentinel.Frooble, create=True)
- def test():
- self.assertEqual(SomeClass.frooble, sentinel.Frooble)
-
- test()
- self.assertFalse(hasattr(SomeClass, 'frooble'))
-
-
- def testPatchWontCreateByDefault(self):
- try:
- @patch('%s.frooble' % builtin_string, sentinel.Frooble)
- def test():
- self.assertEqual(frooble, sentinel.Frooble)
-
- test()
- except AttributeError:
- pass
- else:
- self.fail('Patching non existent attributes should fail')
-
- self.assertRaises(NameError, lambda: frooble)
-
-
- def testPatchObjecWontCreateByDefault(self):
- try:
- @patch.object(SomeClass, 'frooble', sentinel.Frooble)
- def test():
- self.assertEqual(SomeClass.frooble, sentinel.Frooble)
-
- test()
- except AttributeError:
- pass
- else:
- self.fail('Patching non existent attributes should fail')
- self.assertFalse(hasattr(SomeClass, 'frooble'))
-
-
- def testPathWithStaticMethods(self):
- class Foo(object):
- @staticmethod
- def woot():
- return sentinel.Static
-
- @patch.object(Foo, 'woot', staticmethod(lambda: sentinel.Patched))
- def anonymous():
- self.assertEqual(Foo.woot(), sentinel.Patched)
- anonymous()
-
- self.assertEqual(Foo.woot(), sentinel.Static)
-
-
- def testPatchLocal(self):
- foo = sentinel.Foo
- @patch.object(sentinel, 'Foo', 'Foo')
- def anonymous():
- self.assertEqual(sentinel.Foo, 'Foo')
- anonymous()
-
- self.assertEqual(sentinel.Foo, foo)
-
-
- def testPatchSlots(self):
- class Foo(object):
- __slots__ = ('Foo',)
-
- foo = Foo()
- foo.Foo = sentinel.Foo
-
- @patch.object(foo, 'Foo', 'Foo')
- def anonymous():
- self.assertEqual(foo.Foo, 'Foo')
- anonymous()
-
- self.assertEqual(foo.Foo, sentinel.Foo)
-
- def testPatchObjectClassDecorator(self):
- class Something(object):
- attribute = sentinel.Original
-
- class Foo(object):
- def test_method(other_self):
- self.assertEqual(Something.attribute, sentinel.Patched, "unpatched")
- def not_test_method(other_self):
- self.assertEqual(Something.attribute, sentinel.Original, "non-test method patched")
- Foo = patch.object(Something, 'attribute', sentinel.Patched)(Foo)
-
- f = Foo()
- f.test_method()
- f.not_test_method()
-
- self.assertEqual(Something.attribute, sentinel.Original, "patch not restored")
-
-
- def testPatchClassDecorator(self):
- import __main__
- __main__.something = sentinel.Something
-
- class Something(object):
- attribute = sentinel.Original
-
- class Foo(object):
- def test_method(other_self, mock_something):
- self.assertEqual(__main__.something, mock_something, "unpatched")
- def not_test_method(other_self):
- self.assertEqual(__main__.something, sentinel.Something, "non-test method patched")
- Foo = patch('__main__.something')(Foo)
-
- f = Foo()
- f.test_method()
- f.not_test_method()
-
- self.assertEqual(Something.attribute, sentinel.Original, "patch not restored")
- self.assertEqual(__main__.something, sentinel.Something, "patch not restored")
-
- @unittest2.skipUnless(with_available, "test requires Python >= 2.5")
- def testPatchObjectDeprecation(self):
- # needed to enable the deprecation warnings
- warnings.simplefilter('default')
-
- @apply
- @examine_warnings
- def _examine_warnings(ws):
- patch_object(SomeClass, 'class_attribute', spec=SomeClass)
- warning = ws[0]
- self.assertIs(warning.category, DeprecationWarning)
-
- def testPatchObjectTwice(self):
- class Something(object):
- attribute = sentinel.Original
- next_attribute = sentinel.Original2
-
- @apply
- @patch.object(Something, 'attribute', sentinel.Patched)
- @patch.object(Something, 'attribute', sentinel.Patched)
- def test():
- self.assertEqual(Something.attribute, sentinel.Patched, "unpatched")
-
- self.assertEqual(Something.attribute, sentinel.Original, "patch not restored")
-
- def testPatchDict(self):
- foo = {'initial': object(), 'other': 'something'}
- original = foo.copy()
-
- @apply
- @patch.dict(foo)
- def test():
- foo['a'] = 3
- del foo['initial']
- foo['other'] = 'something else'
-
- self.assertEqual(foo, original)
-
- @apply
- @patch.dict(foo, {'a': 'b'})
- def test():
- self.assertEqual(len(foo), 3)
- self.assertEqual(foo['a'], 'b')
-
- self.assertEqual(foo, original)
-
- @apply
- @patch.dict(foo, [('a', 'b')])
- def test():
- self.assertEqual(len(foo), 3)
- self.assertEqual(foo['a'], 'b')
-
- self.assertEqual(foo, original)
-
- def testPatchDictWithContainerObject(self):
- foo = Container()
- foo['initial'] = object()
- foo['other'] = 'something'
-
- original = foo.values.copy()
-
- @apply
- @patch.dict(foo)
- def test():
- foo['a'] = 3
- del foo['initial']
- foo['other'] = 'something else'
-
- self.assertEqual(foo.values, original)
-
- @apply
- @patch.dict(foo, {'a': 'b'})
- def test():
- self.assertEqual(len(foo.values), 3)
- self.assertEqual(foo['a'], 'b')
-
- self.assertEqual(foo.values, original)
-
- def testPatchDictWithClear(self):
- foo = {'initial': object(), 'other': 'something'}
- original = foo.copy()
-
- @apply
- @patch.dict(foo, clear=True)
- def test():
- self.assertEqual(foo, {})
- foo['a'] = 3
- foo['other'] = 'something else'
-
- self.assertEqual(foo, original)
-
- @apply
- @patch.dict(foo, {'a': 'b'}, clear=True)
- def test():
- self.assertEqual(foo, {'a': 'b'})
-
- self.assertEqual(foo, original)
-
- @apply
- @patch.dict(foo, [('a', 'b')], clear=True)
- def test():
- self.assertEqual(foo, {'a': 'b'})
-
- self.assertEqual(foo, original)
-
-
- def testPatchDictWithContainerObjectAndClear(self):
- foo = Container()
- foo['initial'] = object()
- foo['other'] = 'something'
-
- original = foo.values.copy()
-
- @apply
- @patch.dict(foo, clear=True)
- def test():
- self.assertEqual(foo.values, {})
- foo['a'] = 3
- foo['other'] = 'something else'
-
- self.assertEqual(foo.values, original)
-
- @apply
- @patch.dict(foo, {'a': 'b'}, clear=True)
- def test():
- self.assertEqual(foo.values, {'a': 'b'})
-
- self.assertEqual(foo.values, original)
-
- def testNamePreserved(self):
- foo = {}
-
- @patch('tests.testpatch.SomeClass', object())
- @patch('tests.testpatch.SomeClass', object(), mocksignature=True)
- @patch.object(SomeClass, object())
- @patch.dict(foo)
- def some_name():
- pass
-
- self.assertEqual(some_name.__name__, 'some_name')
-
- def testPatchWithException(self):
- foo = {}
-
- @patch.dict(foo, {'a': 'b'})
- def test():
- raise NameError('Konrad')
- try:
- test()
- except NameError:
- pass
- else:
- self.fail('NameError not raised by test')
-
- self.assertEqual(foo, {})
-
- def testPatchDictWithString(self):
- @apply
- @patch.dict('os.environ', {'konrad_delong': 'some value'})
- def test():
- self.assertIn('konrad_delong', os.environ)
-
- def DONTtestPatchDescriptor(self):
- # would be some effort to fix this - we could special case the
- # builtin descriptors: classmethod, property, staticmethod
- class Nothing(object):
- foo = None
-
- class Something(object):
- foo = {}
-
- @patch.object(Nothing, 'foo', 2)
- @classmethod
- def klass(cls):
- self.assertIs(cls, Something)
-
- @patch.object(Nothing, 'foo', 2)
- @staticmethod
- def static(arg):
- return arg
-
- @patch.dict(foo)
- @classmethod
- def klass_dict(cls):
- self.assertIs(cls, Something)
-
- @patch.dict(foo)
- @staticmethod
- def static_dict(arg):
- return arg
-
- # these will raise exceptions if patching descriptors is broken
- self.assertEqual(Something.static('f00'), 'f00')
- Something.klass()
- self.assertEqual(Something.static_dict('f00'), 'f00')
- Something.klass_dict()
-
- something = Something()
- self.assertEqual(something.static('f00'), 'f00')
- something.klass()
- self.assertEqual(something.static_dict('f00'), 'f00')
- something.klass_dict()
-
-
-if __name__ == '__main__':
- unittest2.main()
-
-
\ No newline at end of file +# Copyright (C) 2007-2010 Michael Foord & the mock team +# E-mail: fuzzyman AT voidspace DOT org DOT uk +# http://www.voidspace.org.uk/python/mock/ + +import os +import warnings + +from tests.support import unittest2, apply, inPy3k, SomeClass, with_available + +if with_available: + from tests.support_with import examine_warnings + +from mock import Mock, patch, patch_object, sentinel + +if not inPy3k: + builtin_string = '__builtin__' +else: + builtin_string = 'builtins' + + +# for use in the test +something = sentinel.Something +something_else = sentinel.SomethingElse + + +class Container(object): + def __init__(self): + self.values = {} + + def __getitem__(self, name): + return self.values[name] + + def __setitem__(self, name, value): + self.values[name] = value + + def __delitem__(self, name): + del self.values[name] + + def __iter__(self): + return iter(self.values) + + +class PatchTest(unittest2.TestCase): + + def testSinglePatchObject(self): + class Something(object): + attribute = sentinel.Original + + @apply + @patch.object(Something, 'attribute', sentinel.Patched) + def test(): + self.assertEqual(Something.attribute, sentinel.Patched, "unpatched") + + self.assertEqual(Something.attribute, sentinel.Original, "patch not restored") + + + def testPatchObjectWithNone(self): + class Something(object): + attribute = sentinel.Original + + @apply + @patch.object(Something, 'attribute', None) + def test(): + self.assertIsNone(Something.attribute, "unpatched") + + self.assertEqual(Something.attribute, sentinel.Original, "patch not restored") + + + def testMultiplePatchObject(self): + class Something(object): + attribute = sentinel.Original + next_attribute = sentinel.Original2 + + @apply + @patch.object(Something, 'attribute', sentinel.Patched) + @patch.object(Something, 'next_attribute', sentinel.Patched2) + def test(): + self.assertEqual(Something.attribute, sentinel.Patched, "unpatched") + self.assertEqual(Something.next_attribute, sentinel.Patched2, "unpatched") + + self.assertEqual(Something.attribute, sentinel.Original, "patch not restored") + self.assertEqual(Something.next_attribute, sentinel.Original2, "patch not restored") + + + def testObjectLookupIsQuiteLazy(self): + global something + original = something + @patch('tests.testpatch.something', sentinel.Something2) + def test(): + pass + + try: + something = sentinel.replacement_value + test() + self.assertEqual(something, sentinel.replacement_value) + finally: + something = original + + + def testPatch(self): + import __main__ + __main__.something = sentinel.Something + + @apply + @patch('__main__.something', sentinel.Something2) + def test(): + self.assertEqual(__main__.something, sentinel.Something2, "unpatched") + + self.assertEqual(__main__.something, sentinel.Something, "patch not restored") + + import tests.testpatch as PTModule + + @patch('tests.testpatch.something', sentinel.Something2) + @patch('tests.testpatch.something_else', sentinel.SomethingElse) + def test(): + self.assertEqual(PTModule.something, sentinel.Something2, "unpatched") + self.assertEqual(PTModule.something_else, sentinel.SomethingElse, "unpatched") + + self.assertEqual(PTModule.something, sentinel.Something, "patch not restored") + self.assertEqual(PTModule.something_else, sentinel.SomethingElse, "patch not restored") + + # Test the patching and restoring works a second time + test() + + self.assertEqual(PTModule.something, sentinel.Something, "patch not restored") + self.assertEqual(PTModule.something_else, sentinel.SomethingElse, "patch not restored") + + mock = Mock() + mock.return_value = sentinel.Handle + @patch('%s.open' % builtin_string, mock) + def test(): + self.assertEqual(open('filename', 'r'), sentinel.Handle, "open not patched") + test() + test() + + self.assertNotEquals(open, mock, "patch not restored") + + + def testPatchClassAttribute(self): + import tests.testpatch as PTModule + + @patch('tests.testpatch.SomeClass.class_attribute', sentinel.ClassAttribute) + def test(): + self.assertEqual(PTModule.SomeClass.class_attribute, sentinel.ClassAttribute, "unpatched") + test() + + self.assertIsNone(PTModule.SomeClass.class_attribute, "patch not restored") + + + def testPatchObjectWithDefaultMock(self): + class Test(object): + something = sentinel.Original + something2 = sentinel.Original2 + + @apply + @patch.object(Test, 'something') + def test(mock): + self.assertEqual(mock, Test.something, "Mock not passed into test function") + self.assertTrue(isinstance(mock, Mock), + "patch with two arguments did not create a mock") + + @patch.object(Test, 'something') + @patch.object(Test, 'something2') + def test(this1, this2, mock1, mock2): + self.assertEqual(this1, sentinel.this1, "Patched function didn't receive initial argument") + self.assertEqual(this2, sentinel.this2, "Patched function didn't receive second argument") + self.assertEqual(mock1, Test.something2, "Mock not passed into test function") + self.assertEqual(mock2, Test.something, "Second Mock not passed into test function") + self.assertTrue(isinstance(mock2, Mock), + "patch with two arguments did not create a mock") + self.assertTrue(isinstance(mock2, Mock), + "patch with two arguments did not create a mock") + + + # A hack to test that new mocks are passed the second time + self.assertNotEquals(outerMock1, mock1, "unexpected value for mock1") + self.assertNotEquals(outerMock2, mock2, "unexpected value for mock1") + return mock1, mock2 + + outerMock1 = None + outerMock2 = None + outerMock1, outerMock2 = test(sentinel.this1, sentinel.this2) + + # Test that executing a second time creates new mocks + test(sentinel.this1, sentinel.this2) + + + def testPatchWithSpec(self): + @patch('tests.testpatch.SomeClass', spec=SomeClass) + def test(MockSomeClass): + self.assertEqual(SomeClass, MockSomeClass) + self.assertTrue(isinstance(SomeClass.wibble, Mock)) + self.assertRaises(AttributeError, lambda: SomeClass.not_wibble) + + test() + + + def testPatchObjectWithSpec(self): + @patch.object(SomeClass, 'class_attribute', spec=SomeClass) + def test(MockAttribute): + self.assertEqual(SomeClass.class_attribute, MockAttribute) + self.assertTrue(isinstance(SomeClass.class_attribute.wibble, Mock)) + self.assertRaises(AttributeError, lambda: SomeClass.class_attribute.not_wibble) + + test() + + + def testPatchWithSpecAsList(self): + @patch('tests.testpatch.SomeClass', spec=['wibble']) + def test(MockSomeClass): + self.assertEqual(SomeClass, MockSomeClass) + self.assertTrue(isinstance(SomeClass.wibble, Mock)) + self.assertRaises(AttributeError, lambda: SomeClass.not_wibble) + + test() + + + def testPatchObjectWithSpecAsList(self): + @patch.object(SomeClass, 'class_attribute', spec=['wibble']) + def test(MockAttribute): + self.assertEqual(SomeClass.class_attribute, MockAttribute) + self.assertTrue(isinstance(SomeClass.class_attribute.wibble, Mock)) + self.assertRaises(AttributeError, lambda: SomeClass.class_attribute.not_wibble) + + test() + + + def testNestedPatchWithSpecAsList(self): + # regression test for nested decorators + @patch('%s.open' % builtin_string) + @patch('tests.testpatch.SomeClass', spec=['wibble']) + def test(MockSomeClass, MockOpen): + self.assertEqual(SomeClass, MockSomeClass) + self.assertTrue(isinstance(SomeClass.wibble, Mock)) + self.assertRaises(AttributeError, lambda: SomeClass.not_wibble) + + + def testPatchWithSpecAsBoolean(self): + @apply + @patch('tests.testpatch.SomeClass', spec=True) + def test(MockSomeClass): + self.assertEqual(SomeClass, MockSomeClass) + # Should not raise attribute error + MockSomeClass.wibble + + self.assertRaises(AttributeError, lambda: MockSomeClass.not_wibble) + + + def testPatchObjectWithSpecAsBoolean(self): + from tests import testpatch + @apply + @patch.object(testpatch, 'SomeClass', spec=True) + def test(MockSomeClass): + self.assertEqual(SomeClass, MockSomeClass) + # Should not raise attribute error + MockSomeClass.wibble + + self.assertRaises(AttributeError, lambda: MockSomeClass.not_wibble) + + + def testPatchClassActsWithSpecIsInherited(self): + @apply + @patch('tests.testpatch.SomeClass', spec=True) + def test(MockSomeClass): + instance = MockSomeClass() + # Should not raise attribute error + instance.wibble + + self.assertRaises(AttributeError, lambda: instance.not_wibble) + + + def testPatchWithCreateMocksNonExistentAttributes(self): + @patch('%s.frooble' % builtin_string, sentinel.Frooble, create=True) + def test(): + self.assertEqual(frooble, sentinel.Frooble) + + test() + self.assertRaises(NameError, lambda: frooble) + + + def testPatchObjectWithCreateMocksNonExistentAttributes(self): + @patch.object(SomeClass, 'frooble', sentinel.Frooble, create=True) + def test(): + self.assertEqual(SomeClass.frooble, sentinel.Frooble) + + test() + self.assertFalse(hasattr(SomeClass, 'frooble')) + + + def testPatchWontCreateByDefault(self): + try: + @patch('%s.frooble' % builtin_string, sentinel.Frooble) + def test(): + self.assertEqual(frooble, sentinel.Frooble) + + test() + except AttributeError: + pass + else: + self.fail('Patching non existent attributes should fail') + + self.assertRaises(NameError, lambda: frooble) + + + def testPatchObjecWontCreateByDefault(self): + try: + @patch.object(SomeClass, 'frooble', sentinel.Frooble) + def test(): + self.assertEqual(SomeClass.frooble, sentinel.Frooble) + + test() + except AttributeError: + pass + else: + self.fail('Patching non existent attributes should fail') + self.assertFalse(hasattr(SomeClass, 'frooble')) + + + def testPathWithStaticMethods(self): + class Foo(object): + @staticmethod + def woot(): + return sentinel.Static + + @patch.object(Foo, 'woot', staticmethod(lambda: sentinel.Patched)) + def anonymous(): + self.assertEqual(Foo.woot(), sentinel.Patched) + anonymous() + + self.assertEqual(Foo.woot(), sentinel.Static) + + + def testPatchLocal(self): + foo = sentinel.Foo + @patch.object(sentinel, 'Foo', 'Foo') + def anonymous(): + self.assertEqual(sentinel.Foo, 'Foo') + anonymous() + + self.assertEqual(sentinel.Foo, foo) + + + def testPatchSlots(self): + class Foo(object): + __slots__ = ('Foo',) + + foo = Foo() + foo.Foo = sentinel.Foo + + @patch.object(foo, 'Foo', 'Foo') + def anonymous(): + self.assertEqual(foo.Foo, 'Foo') + anonymous() + + self.assertEqual(foo.Foo, sentinel.Foo) + + def testPatchObjectClassDecorator(self): + class Something(object): + attribute = sentinel.Original + + class Foo(object): + def test_method(other_self): + self.assertEqual(Something.attribute, sentinel.Patched, "unpatched") + def not_test_method(other_self): + self.assertEqual(Something.attribute, sentinel.Original, "non-test method patched") + Foo = patch.object(Something, 'attribute', sentinel.Patched)(Foo) + + f = Foo() + f.test_method() + f.not_test_method() + + self.assertEqual(Something.attribute, sentinel.Original, "patch not restored") + + + def testPatchClassDecorator(self): + import __main__ + __main__.something = sentinel.Something + + class Something(object): + attribute = sentinel.Original + + class Foo(object): + def test_method(other_self, mock_something): + self.assertEqual(__main__.something, mock_something, "unpatched") + def not_test_method(other_self): + self.assertEqual(__main__.something, sentinel.Something, "non-test method patched") + Foo = patch('__main__.something')(Foo) + + f = Foo() + f.test_method() + f.not_test_method() + + self.assertEqual(Something.attribute, sentinel.Original, "patch not restored") + self.assertEqual(__main__.something, sentinel.Something, "patch not restored") + + @unittest2.skipUnless(with_available, "test requires Python >= 2.5") + def testPatchObjectDeprecation(self): + # needed to enable the deprecation warnings + warnings.simplefilter('default') + + @apply + @examine_warnings + def _examine_warnings(ws): + patch_object(SomeClass, 'class_attribute', spec=SomeClass) + warning = ws[0] + self.assertIs(warning.category, DeprecationWarning) + + def testPatchObjectTwice(self): + class Something(object): + attribute = sentinel.Original + next_attribute = sentinel.Original2 + + @apply + @patch.object(Something, 'attribute', sentinel.Patched) + @patch.object(Something, 'attribute', sentinel.Patched) + def test(): + self.assertEqual(Something.attribute, sentinel.Patched, "unpatched") + + self.assertEqual(Something.attribute, sentinel.Original, "patch not restored") + + def testPatchDict(self): + foo = {'initial': object(), 'other': 'something'} + original = foo.copy() + + @apply + @patch.dict(foo) + def test(): + foo['a'] = 3 + del foo['initial'] + foo['other'] = 'something else' + + self.assertEqual(foo, original) + + @apply + @patch.dict(foo, {'a': 'b'}) + def test(): + self.assertEqual(len(foo), 3) + self.assertEqual(foo['a'], 'b') + + self.assertEqual(foo, original) + + @apply + @patch.dict(foo, [('a', 'b')]) + def test(): + self.assertEqual(len(foo), 3) + self.assertEqual(foo['a'], 'b') + + self.assertEqual(foo, original) + + def testPatchDictWithContainerObject(self): + foo = Container() + foo['initial'] = object() + foo['other'] = 'something' + + original = foo.values.copy() + + @apply + @patch.dict(foo) + def test(): + foo['a'] = 3 + del foo['initial'] + foo['other'] = 'something else' + + self.assertEqual(foo.values, original) + + @apply + @patch.dict(foo, {'a': 'b'}) + def test(): + self.assertEqual(len(foo.values), 3) + self.assertEqual(foo['a'], 'b') + + self.assertEqual(foo.values, original) + + def testPatchDictWithClear(self): + foo = {'initial': object(), 'other': 'something'} + original = foo.copy() + + @apply + @patch.dict(foo, clear=True) + def test(): + self.assertEqual(foo, {}) + foo['a'] = 3 + foo['other'] = 'something else' + + self.assertEqual(foo, original) + + @apply + @patch.dict(foo, {'a': 'b'}, clear=True) + def test(): + self.assertEqual(foo, {'a': 'b'}) + + self.assertEqual(foo, original) + + @apply + @patch.dict(foo, [('a', 'b')], clear=True) + def test(): + self.assertEqual(foo, {'a': 'b'}) + + self.assertEqual(foo, original) + + + def testPatchDictWithContainerObjectAndClear(self): + foo = Container() + foo['initial'] = object() + foo['other'] = 'something' + + original = foo.values.copy() + + @apply + @patch.dict(foo, clear=True) + def test(): + self.assertEqual(foo.values, {}) + foo['a'] = 3 + foo['other'] = 'something else' + + self.assertEqual(foo.values, original) + + @apply + @patch.dict(foo, {'a': 'b'}, clear=True) + def test(): + self.assertEqual(foo.values, {'a': 'b'}) + + self.assertEqual(foo.values, original) + + def testNamePreserved(self): + foo = {} + + @patch('tests.testpatch.SomeClass', object()) + @patch('tests.testpatch.SomeClass', object(), mocksignature=True) + @patch.object(SomeClass, object()) + @patch.dict(foo) + def some_name(): + pass + + self.assertEqual(some_name.__name__, 'some_name') + + def testPatchWithException(self): + foo = {} + + @patch.dict(foo, {'a': 'b'}) + def test(): + raise NameError('Konrad') + try: + test() + except NameError: + pass + else: + self.fail('NameError not raised by test') + + self.assertEqual(foo, {}) + + def testPatchDictWithString(self): + @apply + @patch.dict('os.environ', {'konrad_delong': 'some value'}) + def test(): + self.assertIn('konrad_delong', os.environ) + + def DONTtestPatchDescriptor(self): + # would be some effort to fix this - we could special case the + # builtin descriptors: classmethod, property, staticmethod + class Nothing(object): + foo = None + + class Something(object): + foo = {} + + @patch.object(Nothing, 'foo', 2) + @classmethod + def klass(cls): + self.assertIs(cls, Something) + + @patch.object(Nothing, 'foo', 2) + @staticmethod + def static(arg): + return arg + + @patch.dict(foo) + @classmethod + def klass_dict(cls): + self.assertIs(cls, Something) + + @patch.dict(foo) + @staticmethod + def static_dict(arg): + return arg + + # these will raise exceptions if patching descriptors is broken + self.assertEqual(Something.static('f00'), 'f00') + Something.klass() + self.assertEqual(Something.static_dict('f00'), 'f00') + Something.klass_dict() + + something = Something() + self.assertEqual(something.static('f00'), 'f00') + something.klass() + self.assertEqual(something.static_dict('f00'), 'f00') + something.klass_dict() + + +if __name__ == '__main__': + unittest2.main() + diff --git a/tests/testsentinel.py b/tests/testsentinel.py index d11bf49..4c355d7 100644 --- a/tests/testsentinel.py +++ b/tests/testsentinel.py @@ -1,31 +1,30 @@ -# Copyright (C) 2007-2010 Michael Foord & the mock team
-# E-mail: fuzzyman AT voidspace DOT org DOT uk
-# http://www.voidspace.org.uk/python/mock/
-
-from tests.support import unittest2
-
-from mock import sentinel, DEFAULT
-
-
-class SentinelTest(unittest2.TestCase):
-
- def testSentinels(self):
- self.assertEqual(sentinel.whatever, sentinel.whatever, 'sentinel not stored')
- self.assertNotEquals(sentinel.whatever, sentinel.whateverelse, 'sentinel should be unique')
-
-
- def testSentinelName(self):
- self.assertEqual(str(sentinel.whatever), '<SentinelObject "whatever">', 'sentinel name incorrect')
-
-
- def testDEFAULT(self):
- self.assertTrue(DEFAULT is sentinel.DEFAULT)
-
- def testBases(self):
- # If this doesn't raise an AttributeError then help(mock) is broken
- self.assertRaises(AttributeError, lambda: sentinel.__bases__)
-
-
-if __name__ == '__main__':
- unittest2.main()
-
+# Copyright (C) 2007-2010 Michael Foord & the mock team +# E-mail: fuzzyman AT voidspace DOT org DOT uk +# http://www.voidspace.org.uk/python/mock/ + +from tests.support import unittest2 + +from mock import sentinel, DEFAULT + + +class SentinelTest(unittest2.TestCase): + + def testSentinels(self): + self.assertEqual(sentinel.whatever, sentinel.whatever, 'sentinel not stored') + self.assertNotEquals(sentinel.whatever, sentinel.whateverelse, 'sentinel should be unique') + + + def testSentinelName(self): + self.assertEqual(str(sentinel.whatever), '<SentinelObject "whatever">', 'sentinel name incorrect') + + + def testDEFAULT(self): + self.assertTrue(DEFAULT is sentinel.DEFAULT) + + def testBases(self): + # If this doesn't raise an AttributeError then help(mock) is broken + self.assertRaises(AttributeError, lambda: sentinel.__bases__) + + +if __name__ == '__main__': + unittest2.main() diff --git a/tests/testwith.py b/tests/testwith.py index baecd35..411cdbf 100644 --- a/tests/testwith.py +++ b/tests/testwith.py @@ -18,13 +18,13 @@ class WithTest(unittest2.TestCase): def testWithStatement(self): with patch('tests.testwith.something', sentinel.Something2): - self.assertEqual(something, sentinel.Something2, "unpatched") + self.assertEqual(something, sentinel.Something2, "unpatched") self.assertEqual(something, sentinel.Something) - + def testWithStatementException(self): try: with patch('tests.testwith.something', sentinel.Something2): - self.assertEqual(something, sentinel.Something2, "unpatched") + self.assertEqual(something, sentinel.Something2, "unpatched") raise Exception('pow') except Exception: pass @@ -35,7 +35,7 @@ class WithTest(unittest2.TestCase): def testWithStatementAs(self): with patch('tests.testwith.something') as mock_something: - self.assertEqual(something, mock_something, "unpatched") + self.assertEqual(something, mock_something, "unpatched") self.assertTrue(isinstance(mock_something, Mock), "patching wrong type") self.assertEqual(something, sentinel.Something) @@ -44,14 +44,14 @@ class WithTest(unittest2.TestCase): mock = Mock() original = mock.something with patch.object(mock, 'something'): - self.assertNotEquals(mock.something, original, "unpatched") + self.assertNotEquals(mock.something, original, "unpatched") self.assertEqual(mock.something, original) def testWithStatementNested(self): with catch_warnings(record=True): # nested is deprecated in Python 2.7 - with nested(patch('tests.testwith.something'), + with nested(patch('tests.testwith.something'), patch('tests.testwith.something_else')) as (mock_something, mock_something_else): self.assertEqual(something, mock_something, "unpatched") self.assertEqual(something_else, mock_something_else, "unpatched") @@ -61,26 +61,26 @@ class WithTest(unittest2.TestCase): def testWithStatementSpecified(self): with patch('tests.testwith.something', sentinel.Patched) as mock_something: - self.assertEqual(something, mock_something, "unpatched") - self.assertEqual(mock_something, sentinel.Patched, "wrong patch") + self.assertEqual(something, mock_something, "unpatched") + self.assertEqual(mock_something, sentinel.Patched, "wrong patch") self.assertEqual(something, sentinel.Something) - + def testContextManagerMocking(self): mock = Mock() mock.__enter__ = Mock() mock.__exit__ = Mock() mock.__exit__.return_value = False - + with mock as m: self.assertEqual(m, mock.__enter__.return_value) mock.__enter__.assert_called_with() mock.__exit__.assert_called_with(None, None, None) - + def testContextManagerWithMagicMock(self): mock = MagicMock() - + with self.assertRaises(TypeError): with mock: 'foo' + 3 @@ -102,10 +102,10 @@ class WithTest(unittest2.TestCase): def testWithStatementImbricated(self): with patch('tests.testwith.something') as mock_something: self.assertEqual(something, mock_something, "unpatched") - - with patch('tests.testwith.something_else') as mock_something_else: + + with patch('tests.testwith.something_else') as mock_something_else: self.assertEqual(something_else, mock_something_else, "unpatched") - + self.assertEqual(something, sentinel.Something) self.assertEqual(something_else, sentinel.SomethingElse) @@ -114,15 +114,14 @@ class WithTest(unittest2.TestCase): with patch.dict(foo, {'a': 'b'}): self.assertEqual(foo, {'a': 'b'}) self.assertEqual(foo, {}) - + with self.assertRaises(NameError): with patch.dict(foo, {'a': 'b'}): self.assertEqual(foo, {'a': 'b'}) raise NameError('Konrad') - + self.assertEqual(foo, {}) if __name__ == '__main__': unittest2.main() - |