mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-31 14:15:30 +00:00
1352 lines
41 KiB
Python
1352 lines
41 KiB
Python
# Copyright (C) 2007-2012 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 (
|
|
callable, unittest2, inPy3k, is_instance, next
|
|
)
|
|
|
|
import copy
|
|
import pickle
|
|
import sys
|
|
|
|
import mock
|
|
from mock import (
|
|
call, DEFAULT, patch, sentinel,
|
|
MagicMock, Mock, NonCallableMock,
|
|
NonCallableMagicMock, _CallList,
|
|
create_autospec
|
|
)
|
|
|
|
|
|
try:
|
|
unicode
|
|
except NameError:
|
|
unicode = str
|
|
|
|
|
|
class Iter(object):
|
|
def __init__(self):
|
|
self.thing = iter(['this', 'is', 'an', 'iter'])
|
|
|
|
def __iter__(self):
|
|
return self
|
|
|
|
def next(self):
|
|
return next(self.thing)
|
|
|
|
__next__ = next
|
|
|
|
|
|
class Subclass(MagicMock):
|
|
pass
|
|
|
|
|
|
class Thing(object):
|
|
attribute = 6
|
|
foo = 'bar'
|
|
|
|
|
|
|
|
class MockTest(unittest2.TestCase):
|
|
|
|
def test_all(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 test_constructor(self):
|
|
mock = Mock()
|
|
|
|
self.assertFalse(mock.called, "called not initialised correctly")
|
|
self.assertEqual(mock.call_count, 0,
|
|
"call_count not initialised correctly")
|
|
self.assertTrue(is_instance(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._mock_parent,
|
|
"parent not initialised correctly")
|
|
self.assertIsNone(mock._mock_methods,
|
|
"methods not initialised correctly")
|
|
self.assertEqual(mock._mock_children, {},
|
|
"children not initialised incorrectly")
|
|
|
|
|
|
def test_unicode_not_broken(self):
|
|
# This used to raise an exception with Python 2.5 and Mock 0.4
|
|
unicode(Mock())
|
|
|
|
|
|
def test_return_value_in_constructor(self):
|
|
mock = Mock(return_value=None)
|
|
self.assertIsNone(mock.return_value,
|
|
"return value in constructor not honoured")
|
|
|
|
|
|
def test_repr(self):
|
|
mock = Mock(name='foo')
|
|
self.assertIn('foo', repr(mock))
|
|
self.assertIn("'%s'" % id(mock), repr(mock))
|
|
|
|
mocks = [(Mock(), 'mock'), (Mock(name='bar'), 'bar')]
|
|
for mock, name in mocks:
|
|
self.assertIn('%s.bar' % name, repr(mock.bar))
|
|
self.assertIn('%s.foo()' % name, repr(mock.foo()))
|
|
self.assertIn('%s.foo().bing' % name, repr(mock.foo().bing))
|
|
self.assertIn('%s()' % name, repr(mock()))
|
|
self.assertIn('%s()()' % name, repr(mock()()))
|
|
self.assertIn('%s()().foo.bar.baz().bing' % name,
|
|
repr(mock()().foo.bar.baz().bing))
|
|
|
|
|
|
def test_repr_with_spec(self):
|
|
class X(object):
|
|
pass
|
|
|
|
mock = Mock(spec=X)
|
|
self.assertIn(" spec='X' ", repr(mock))
|
|
|
|
mock = Mock(spec=X())
|
|
self.assertIn(" spec='X' ", repr(mock))
|
|
|
|
mock = Mock(spec_set=X)
|
|
self.assertIn(" spec_set='X' ", repr(mock))
|
|
|
|
mock = Mock(spec_set=X())
|
|
self.assertIn(" spec_set='X' ", repr(mock))
|
|
|
|
mock = Mock(spec=X, name='foo')
|
|
self.assertIn(" spec='X' ", repr(mock))
|
|
self.assertIn(" name='foo' ", repr(mock))
|
|
|
|
mock = Mock(name='foo')
|
|
self.assertNotIn("spec", repr(mock))
|
|
|
|
mock = Mock()
|
|
self.assertNotIn("spec", repr(mock))
|
|
|
|
mock = Mock(spec=['foo'])
|
|
self.assertNotIn("spec", repr(mock))
|
|
|
|
|
|
def test_side_effect(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)
|
|
|
|
|
|
@unittest2.skipUnless('java' in sys.platform,
|
|
'This test only applies to Jython')
|
|
def test_java_exception_side_effect(self):
|
|
import java
|
|
mock = Mock(side_effect=java.lang.RuntimeException("Boom!"))
|
|
|
|
# can't use assertRaises with java exceptions
|
|
try:
|
|
mock(1, 2, fish=3)
|
|
except java.lang.RuntimeException:
|
|
pass
|
|
else:
|
|
self.fail('java exception not raised')
|
|
mock.assert_called_with(1,2, fish=3)
|
|
|
|
|
|
def test_reset_mock(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._mock_name, "child",
|
|
"name incorrectly reset")
|
|
self.assertEqual(mock._mock_parent, parent,
|
|
"parent incorrectly reset")
|
|
self.assertEqual(mock._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.mock_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._mock_children, {'something': something},
|
|
"children reset incorrectly")
|
|
self.assertEqual(mock.something, something,
|
|
"children incorrectly cleared")
|
|
self.assertFalse(mock.something.called, "child not reset")
|
|
|
|
|
|
def test_reset_mock_recursion(self):
|
|
mock = Mock()
|
|
mock.return_value = mock
|
|
|
|
# used to cause recursion
|
|
mock.reset_mock()
|
|
|
|
|
|
def test_call(self):
|
|
mock = Mock()
|
|
self.assertTrue(is_instance(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 test_call_args_comparison(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 test_assert_called_with(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 test_assert_called_once_with(self):
|
|
mock = Mock()
|
|
mock()
|
|
|
|
# Will raise an exception if it fails
|
|
mock.assert_called_once_with()
|
|
|
|
mock()
|
|
self.assertRaises(AssertionError, mock.assert_called_once_with)
|
|
|
|
mock.reset_mock()
|
|
self.assertRaises(AssertionError, mock.assert_called_once_with)
|
|
|
|
mock('foo', 'bar', baz=2)
|
|
mock.assert_called_once_with('foo', 'bar', baz=2)
|
|
|
|
mock.reset_mock()
|
|
mock('foo', 'bar', baz=2)
|
|
self.assertRaises(
|
|
AssertionError,
|
|
lambda: mock.assert_called_once_with('bob', 'bar', baz=2)
|
|
)
|
|
|
|
|
|
def test_attribute_access_returns_mocks(self):
|
|
mock = Mock()
|
|
something = mock.something
|
|
self.assertTrue(is_instance(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 test_attributes_have_name_and_parent_set(self):
|
|
mock = Mock()
|
|
something = mock.something
|
|
|
|
self.assertEqual(something._mock_name, "something",
|
|
"attribute name not set correctly")
|
|
self.assertEqual(something._mock_parent, mock,
|
|
"attribute parent not set correctly")
|
|
|
|
|
|
def test_method_calls_recorded(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 test_method_calls_compare_easily(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 test_only_allowed_methods_exist(self):
|
|
for spec in ['something'], ('something',):
|
|
for arg in 'spec', 'spec_set':
|
|
mock = Mock(**{arg: spec})
|
|
|
|
# this should be allowed
|
|
mock.something
|
|
self.assertRaisesRegexp(
|
|
AttributeError,
|
|
"Mock object has no attribute 'something_else'",
|
|
getattr, mock, 'something_else'
|
|
)
|
|
|
|
|
|
def test_from_spec(self):
|
|
class Something(object):
|
|
x = 3
|
|
__something__ = None
|
|
def y(self):
|
|
pass
|
|
|
|
def test_attributes(mock):
|
|
# should work
|
|
mock.x
|
|
mock.y
|
|
mock.__something__
|
|
self.assertRaisesRegexp(
|
|
AttributeError,
|
|
"Mock object has no attribute 'z'",
|
|
getattr, mock, 'z'
|
|
)
|
|
self.assertRaisesRegexp(
|
|
AttributeError,
|
|
"Mock object has no attribute '__foobar__'",
|
|
getattr, mock, '__foobar__'
|
|
)
|
|
|
|
test_attributes(Mock(spec=Something))
|
|
test_attributes(Mock(spec=Something()))
|
|
|
|
|
|
def test_wraps_calls(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 test_wraps_call_with_nondefault_return_value(self):
|
|
real = Mock()
|
|
|
|
mock = Mock(wraps=real)
|
|
mock.return_value = 3
|
|
|
|
self.assertEqual(mock(), 3)
|
|
self.assertFalse(real.called)
|
|
|
|
|
|
def test_wraps_attributes(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 test_exceptional_side_effect(self):
|
|
mock = Mock(side_effect=AttributeError)
|
|
self.assertRaises(AttributeError, mock)
|
|
|
|
mock = Mock(side_effect=AttributeError('foo'))
|
|
self.assertRaises(AttributeError, mock)
|
|
|
|
|
|
def test_baseexceptional_side_effect(self):
|
|
mock = Mock(side_effect=KeyboardInterrupt)
|
|
self.assertRaises(KeyboardInterrupt, mock)
|
|
|
|
mock = Mock(side_effect=KeyboardInterrupt('foo'))
|
|
self.assertRaises(KeyboardInterrupt, mock)
|
|
|
|
|
|
def test_assert_called_with_message(self):
|
|
mock = Mock()
|
|
self.assertRaisesRegexp(AssertionError, 'Not called',
|
|
mock.assert_called_with)
|
|
|
|
|
|
def test__name__(self):
|
|
mock = Mock()
|
|
self.assertRaises(AttributeError, lambda: mock.__name__)
|
|
|
|
mock.__name__ = 'foo'
|
|
self.assertEqual(mock.__name__, 'foo')
|
|
|
|
|
|
def test_spec_list_subclass(self):
|
|
class Sub(list):
|
|
pass
|
|
mock = Mock(spec=Sub(['foo']))
|
|
|
|
mock.append(3)
|
|
mock.append.assert_called_with(3)
|
|
self.assertRaises(AttributeError, getattr, mock, 'foo')
|
|
|
|
|
|
def test_spec_class(self):
|
|
class X(object):
|
|
pass
|
|
|
|
mock = Mock(spec=X)
|
|
self.assertTrue(isinstance(mock, X))
|
|
|
|
mock = Mock(spec=X())
|
|
self.assertTrue(isinstance(mock, X))
|
|
|
|
self.assertIs(mock.__class__, X)
|
|
self.assertEqual(Mock().__class__.__name__, 'Mock')
|
|
|
|
mock = Mock(spec_set=X)
|
|
self.assertTrue(isinstance(mock, X))
|
|
|
|
mock = Mock(spec_set=X())
|
|
self.assertTrue(isinstance(mock, X))
|
|
|
|
|
|
def test_setting_attribute_with_spec_set(self):
|
|
class X(object):
|
|
y = 3
|
|
|
|
mock = Mock(spec=X)
|
|
mock.x = 'foo'
|
|
|
|
mock = Mock(spec_set=X)
|
|
def set_attr():
|
|
mock.x = 'foo'
|
|
|
|
mock.y = 'foo'
|
|
self.assertRaises(AttributeError, set_attr)
|
|
|
|
|
|
def test_copy(self):
|
|
current = sys.getrecursionlimit()
|
|
self.addCleanup(sys.setrecursionlimit, current)
|
|
|
|
# can't use sys.maxint as this doesn't exist in Python 3
|
|
sys.setrecursionlimit(int(10e8))
|
|
# this segfaults without the fix in place
|
|
copy.copy(Mock())
|
|
|
|
|
|
@unittest2.skipIf(inPy3k, "no old style classes in Python 3")
|
|
def test_spec_old_style_classes(self):
|
|
class Foo:
|
|
bar = 7
|
|
|
|
mock = Mock(spec=Foo)
|
|
mock.bar = 6
|
|
self.assertRaises(AttributeError, lambda: mock.foo)
|
|
|
|
mock = Mock(spec=Foo())
|
|
mock.bar = 6
|
|
self.assertRaises(AttributeError, lambda: mock.foo)
|
|
|
|
|
|
@unittest2.skipIf(inPy3k, "no old style classes in Python 3")
|
|
def test_spec_set_old_style_classes(self):
|
|
class Foo:
|
|
bar = 7
|
|
|
|
mock = Mock(spec_set=Foo)
|
|
mock.bar = 6
|
|
self.assertRaises(AttributeError, lambda: mock.foo)
|
|
|
|
def _set():
|
|
mock.foo = 3
|
|
self.assertRaises(AttributeError, _set)
|
|
|
|
mock = Mock(spec_set=Foo())
|
|
mock.bar = 6
|
|
self.assertRaises(AttributeError, lambda: mock.foo)
|
|
|
|
def _set():
|
|
mock.foo = 3
|
|
self.assertRaises(AttributeError, _set)
|
|
|
|
|
|
def test_subclass_with_properties(self):
|
|
class SubClass(Mock):
|
|
def _get(self):
|
|
return 3
|
|
def _set(self, value):
|
|
raise NameError('strange error')
|
|
some_attribute = property(_get, _set)
|
|
|
|
s = SubClass(spec_set=SubClass)
|
|
self.assertEqual(s.some_attribute, 3)
|
|
|
|
def test():
|
|
s.some_attribute = 3
|
|
self.assertRaises(NameError, test)
|
|
|
|
def test():
|
|
s.foo = 'bar'
|
|
self.assertRaises(AttributeError, test)
|
|
|
|
|
|
def test_setting_call(self):
|
|
mock = Mock()
|
|
def __call__(self, a):
|
|
return self._mock_call(a)
|
|
|
|
type(mock).__call__ = __call__
|
|
mock('one')
|
|
mock.assert_called_with('one')
|
|
|
|
self.assertRaises(TypeError, mock, 'one', 'two')
|
|
|
|
|
|
@unittest2.skipUnless(sys.version_info[:2] >= (2, 6),
|
|
"__dir__ not available until Python 2.6 or later")
|
|
def test_dir(self):
|
|
mock = Mock()
|
|
attrs = set(dir(mock))
|
|
type_attrs = set([m for m in dir(Mock) if not m.startswith('_')])
|
|
|
|
# all public attributes from the type are included
|
|
self.assertEqual(set(), type_attrs - attrs)
|
|
|
|
# creates these attributes
|
|
mock.a, mock.b
|
|
self.assertIn('a', dir(mock))
|
|
self.assertIn('b', dir(mock))
|
|
|
|
# instance attributes
|
|
mock.c = mock.d = None
|
|
self.assertIn('c', dir(mock))
|
|
self.assertIn('d', dir(mock))
|
|
|
|
# magic methods
|
|
mock.__iter__ = lambda s: iter([])
|
|
self.assertIn('__iter__', dir(mock))
|
|
|
|
|
|
@unittest2.skipUnless(sys.version_info[:2] >= (2, 6),
|
|
"__dir__ not available until Python 2.6 or later")
|
|
def test_dir_from_spec(self):
|
|
mock = Mock(spec=unittest2.TestCase)
|
|
testcase_attrs = set(dir(unittest2.TestCase))
|
|
attrs = set(dir(mock))
|
|
|
|
# all attributes from the spec are included
|
|
self.assertEqual(set(), testcase_attrs - attrs)
|
|
|
|
# shadow a sys attribute
|
|
mock.version = 3
|
|
self.assertEqual(dir(mock).count('version'), 1)
|
|
|
|
|
|
@unittest2.skipUnless(sys.version_info[:2] >= (2, 6),
|
|
"__dir__ not available until Python 2.6 or later")
|
|
def test_filter_dir(self):
|
|
patcher = patch.object(mock, 'FILTER_DIR', False)
|
|
patcher.start()
|
|
try:
|
|
attrs = set(dir(Mock()))
|
|
type_attrs = set(dir(Mock))
|
|
|
|
# ALL attributes from the type are included
|
|
self.assertEqual(set(), type_attrs - attrs)
|
|
finally:
|
|
patcher.stop()
|
|
|
|
|
|
def test_configure_mock(self):
|
|
mock = Mock(foo='bar')
|
|
self.assertEqual(mock.foo, 'bar')
|
|
|
|
mock = MagicMock(foo='bar')
|
|
self.assertEqual(mock.foo, 'bar')
|
|
|
|
kwargs = {'side_effect': KeyError, 'foo.bar.return_value': 33,
|
|
'foo': MagicMock()}
|
|
mock = Mock(**kwargs)
|
|
self.assertRaises(KeyError, mock)
|
|
self.assertEqual(mock.foo.bar(), 33)
|
|
self.assertIsInstance(mock.foo, MagicMock)
|
|
|
|
mock = Mock()
|
|
mock.configure_mock(**kwargs)
|
|
self.assertRaises(KeyError, mock)
|
|
self.assertEqual(mock.foo.bar(), 33)
|
|
self.assertIsInstance(mock.foo, MagicMock)
|
|
|
|
|
|
def assertRaisesWithMsg(self, exception, message, func, *args, **kwargs):
|
|
# needed because assertRaisesRegex doesn't work easily with newlines
|
|
try:
|
|
func(*args, **kwargs)
|
|
except:
|
|
instance = sys.exc_info()[1]
|
|
self.assertIsInstance(instance, exception)
|
|
else:
|
|
self.fail('Exception %r not raised' % (exception,))
|
|
|
|
msg = str(instance)
|
|
self.assertEqual(msg, message)
|
|
|
|
|
|
def test_assert_called_with_failure_message(self):
|
|
mock = NonCallableMock()
|
|
|
|
expected = "mock(1, '2', 3, bar='foo')"
|
|
message = 'Expected call: %s\nNot called'
|
|
self.assertRaisesWithMsg(
|
|
AssertionError, message % (expected,),
|
|
mock.assert_called_with, 1, '2', 3, bar='foo'
|
|
)
|
|
|
|
mock.foo(1, '2', 3, foo='foo')
|
|
|
|
|
|
asserters = [
|
|
mock.foo.assert_called_with, mock.foo.assert_called_once_with
|
|
]
|
|
for meth in asserters:
|
|
actual = "foo(1, '2', 3, foo='foo')"
|
|
expected = "foo(1, '2', 3, bar='foo')"
|
|
message = 'Expected call: %s\nActual call: %s'
|
|
self.assertRaisesWithMsg(
|
|
AssertionError, message % (expected, actual),
|
|
meth, 1, '2', 3, bar='foo'
|
|
)
|
|
|
|
# just kwargs
|
|
for meth in asserters:
|
|
actual = "foo(1, '2', 3, foo='foo')"
|
|
expected = "foo(bar='foo')"
|
|
message = 'Expected call: %s\nActual call: %s'
|
|
self.assertRaisesWithMsg(
|
|
AssertionError, message % (expected, actual),
|
|
meth, bar='foo'
|
|
)
|
|
|
|
# just args
|
|
for meth in asserters:
|
|
actual = "foo(1, '2', 3, foo='foo')"
|
|
expected = "foo(1, 2, 3)"
|
|
message = 'Expected call: %s\nActual call: %s'
|
|
self.assertRaisesWithMsg(
|
|
AssertionError, message % (expected, actual),
|
|
meth, 1, 2, 3
|
|
)
|
|
|
|
# empty
|
|
for meth in asserters:
|
|
actual = "foo(1, '2', 3, foo='foo')"
|
|
expected = "foo()"
|
|
message = 'Expected call: %s\nActual call: %s'
|
|
self.assertRaisesWithMsg(
|
|
AssertionError, message % (expected, actual), meth
|
|
)
|
|
|
|
|
|
def test_mock_calls(self):
|
|
mock = MagicMock()
|
|
|
|
# need to do this because MagicMock.mock_calls used to just return
|
|
# a MagicMock which also returned a MagicMock when __eq__ was called
|
|
self.assertIs(mock.mock_calls == [], True)
|
|
|
|
mock = MagicMock()
|
|
mock()
|
|
expected = [('', (), {})]
|
|
self.assertEqual(mock.mock_calls, expected)
|
|
|
|
mock.foo()
|
|
expected.append(call.foo())
|
|
self.assertEqual(mock.mock_calls, expected)
|
|
# intermediate mock_calls work too
|
|
self.assertEqual(mock.foo.mock_calls, [('', (), {})])
|
|
|
|
mock = MagicMock()
|
|
mock().foo(1, 2, 3, a=4, b=5)
|
|
expected = [
|
|
('', (), {}), ('().foo', (1, 2, 3), dict(a=4, b=5))
|
|
]
|
|
self.assertEqual(mock.mock_calls, expected)
|
|
self.assertEqual(mock.return_value.foo.mock_calls,
|
|
[('', (1, 2, 3), dict(a=4, b=5))])
|
|
self.assertEqual(mock.return_value.mock_calls,
|
|
[('foo', (1, 2, 3), dict(a=4, b=5))])
|
|
|
|
mock = MagicMock()
|
|
mock().foo.bar().baz()
|
|
expected = [
|
|
('', (), {}), ('().foo.bar', (), {}),
|
|
('().foo.bar().baz', (), {})
|
|
]
|
|
self.assertEqual(mock.mock_calls, expected)
|
|
self.assertEqual(mock().mock_calls,
|
|
call.foo.bar().baz().call_list())
|
|
|
|
for kwargs in dict(), dict(name='bar'):
|
|
mock = MagicMock(**kwargs)
|
|
int(mock.foo)
|
|
expected = [('foo.__int__', (), {})]
|
|
self.assertEqual(mock.mock_calls, expected)
|
|
|
|
mock = MagicMock(**kwargs)
|
|
mock.a()()
|
|
expected = [('a', (), {}), ('a()', (), {})]
|
|
self.assertEqual(mock.mock_calls, expected)
|
|
self.assertEqual(mock.a().mock_calls, [call()])
|
|
|
|
mock = MagicMock(**kwargs)
|
|
mock(1)(2)(3)
|
|
self.assertEqual(mock.mock_calls, call(1)(2)(3).call_list())
|
|
self.assertEqual(mock().mock_calls, call(2)(3).call_list())
|
|
self.assertEqual(mock()().mock_calls, call(3).call_list())
|
|
|
|
mock = MagicMock(**kwargs)
|
|
mock(1)(2)(3).a.b.c(4)
|
|
self.assertEqual(mock.mock_calls,
|
|
call(1)(2)(3).a.b.c(4).call_list())
|
|
self.assertEqual(mock().mock_calls,
|
|
call(2)(3).a.b.c(4).call_list())
|
|
self.assertEqual(mock()().mock_calls,
|
|
call(3).a.b.c(4).call_list())
|
|
|
|
mock = MagicMock(**kwargs)
|
|
int(mock().foo.bar().baz())
|
|
last_call = ('().foo.bar().baz().__int__', (), {})
|
|
self.assertEqual(mock.mock_calls[-1], last_call)
|
|
self.assertEqual(mock().mock_calls,
|
|
call.foo.bar().baz().__int__().call_list())
|
|
self.assertEqual(mock().foo.bar().mock_calls,
|
|
call.baz().__int__().call_list())
|
|
self.assertEqual(mock().foo.bar().baz.mock_calls,
|
|
call().__int__().call_list())
|
|
|
|
|
|
def test_subclassing(self):
|
|
class Subclass(Mock):
|
|
pass
|
|
|
|
mock = Subclass()
|
|
self.assertIsInstance(mock.foo, Subclass)
|
|
self.assertIsInstance(mock(), Subclass)
|
|
|
|
class Subclass(Mock):
|
|
def _get_child_mock(self, **kwargs):
|
|
return Mock(**kwargs)
|
|
|
|
mock = Subclass()
|
|
self.assertNotIsInstance(mock.foo, Subclass)
|
|
self.assertNotIsInstance(mock(), Subclass)
|
|
|
|
|
|
def test_arg_lists(self):
|
|
mocks = [
|
|
Mock(),
|
|
MagicMock(),
|
|
NonCallableMock(),
|
|
NonCallableMagicMock()
|
|
]
|
|
|
|
def assert_attrs(mock):
|
|
names = 'call_args_list', 'method_calls', 'mock_calls'
|
|
for name in names:
|
|
attr = getattr(mock, name)
|
|
self.assertIsInstance(attr, _CallList)
|
|
self.assertIsInstance(attr, list)
|
|
self.assertEqual(attr, [])
|
|
|
|
for mock in mocks:
|
|
assert_attrs(mock)
|
|
|
|
if callable(mock):
|
|
mock()
|
|
mock(1, 2)
|
|
mock(a=3)
|
|
|
|
mock.reset_mock()
|
|
assert_attrs(mock)
|
|
|
|
mock.foo()
|
|
mock.foo.bar(1, a=3)
|
|
mock.foo(1).bar().baz(3)
|
|
|
|
mock.reset_mock()
|
|
assert_attrs(mock)
|
|
|
|
|
|
def test_call_args_two_tuple(self):
|
|
mock = Mock()
|
|
mock(1, a=3)
|
|
mock(2, b=4)
|
|
|
|
self.assertEqual(len(mock.call_args), 2)
|
|
args, kwargs = mock.call_args
|
|
self.assertEqual(args, (2,))
|
|
self.assertEqual(kwargs, dict(b=4))
|
|
|
|
expected_list = [((1,), dict(a=3)), ((2,), dict(b=4))]
|
|
for expected, call_args in zip(expected_list, mock.call_args_list):
|
|
self.assertEqual(len(call_args), 2)
|
|
self.assertEqual(expected[0], call_args[0])
|
|
self.assertEqual(expected[1], call_args[1])
|
|
|
|
|
|
def test_side_effect_iterator(self):
|
|
mock = Mock(side_effect=iter([1, 2, 3]))
|
|
self.assertEqual([mock(), mock(), mock()], [1, 2, 3])
|
|
self.assertRaises(StopIteration, mock)
|
|
|
|
mock = MagicMock(side_effect=['a', 'b', 'c'])
|
|
self.assertEqual([mock(), mock(), mock()], ['a', 'b', 'c'])
|
|
self.assertRaises(StopIteration, mock)
|
|
|
|
mock = Mock(side_effect='ghi')
|
|
self.assertEqual([mock(), mock(), mock()], ['g', 'h', 'i'])
|
|
self.assertRaises(StopIteration, mock)
|
|
|
|
class Foo(object):
|
|
pass
|
|
mock = MagicMock(side_effect=Foo)
|
|
self.assertIsInstance(mock(), Foo)
|
|
|
|
mock = Mock(side_effect=Iter())
|
|
self.assertEqual([mock(), mock(), mock(), mock()],
|
|
['this', 'is', 'an', 'iter'])
|
|
self.assertRaises(StopIteration, mock)
|
|
|
|
|
|
def test_side_effect_setting_iterator(self):
|
|
mock = Mock()
|
|
mock.side_effect = iter([1, 2, 3])
|
|
self.assertEqual([mock(), mock(), mock()], [1, 2, 3])
|
|
self.assertRaises(StopIteration, mock)
|
|
side_effect = mock.side_effect
|
|
self.assertIsInstance(side_effect, type(iter([])))
|
|
|
|
mock.side_effect = ['a', 'b', 'c']
|
|
self.assertEqual([mock(), mock(), mock()], ['a', 'b', 'c'])
|
|
self.assertRaises(StopIteration, mock)
|
|
side_effect = mock.side_effect
|
|
self.assertIsInstance(side_effect, type(iter([])))
|
|
|
|
this_iter = Iter()
|
|
mock.side_effect = this_iter
|
|
self.assertEqual([mock(), mock(), mock(), mock()],
|
|
['this', 'is', 'an', 'iter'])
|
|
self.assertRaises(StopIteration, mock)
|
|
self.assertIs(mock.side_effect, this_iter)
|
|
|
|
|
|
def test_side_effect_iterator_exceptions(self):
|
|
for Klass in Mock, MagicMock:
|
|
iterable = (ValueError, 3, KeyError, 6)
|
|
m = Klass(side_effect=iterable)
|
|
self.assertRaises(ValueError, m)
|
|
self.assertEqual(m(), 3)
|
|
self.assertRaises(KeyError, m)
|
|
self.assertEqual(m(), 6)
|
|
|
|
|
|
def test_assert_has_calls_any_order(self):
|
|
mock = Mock()
|
|
mock(1, 2)
|
|
mock(a=3)
|
|
mock(3, 4)
|
|
mock(b=6)
|
|
mock(b=6)
|
|
|
|
kalls = [
|
|
call(1, 2), ({'a': 3},),
|
|
((3, 4),), ((), {'a': 3}),
|
|
('', (1, 2)), ('', {'a': 3}),
|
|
('', (1, 2), {}), ('', (), {'a': 3})
|
|
]
|
|
for kall in kalls:
|
|
mock.assert_has_calls([kall], any_order=True)
|
|
|
|
for kall in call(1, '2'), call(b=3), call(), 3, None, 'foo':
|
|
self.assertRaises(
|
|
AssertionError, mock.assert_has_calls,
|
|
[kall], any_order=True
|
|
)
|
|
|
|
kall_lists = [
|
|
[call(1, 2), call(b=6)],
|
|
[call(3, 4), call(1, 2)],
|
|
[call(b=6), call(b=6)],
|
|
]
|
|
|
|
for kall_list in kall_lists:
|
|
mock.assert_has_calls(kall_list, any_order=True)
|
|
|
|
kall_lists = [
|
|
[call(b=6), call(b=6), call(b=6)],
|
|
[call(1, 2), call(1, 2)],
|
|
[call(3, 4), call(1, 2), call(5, 7)],
|
|
[call(b=6), call(3, 4), call(b=6), call(1, 2), call(b=6)],
|
|
]
|
|
for kall_list in kall_lists:
|
|
self.assertRaises(
|
|
AssertionError, mock.assert_has_calls,
|
|
kall_list, any_order=True
|
|
)
|
|
|
|
def test_assert_has_calls(self):
|
|
kalls1 = [
|
|
call(1, 2), ({'a': 3},),
|
|
((3, 4),), call(b=6),
|
|
('', (1,), {'b': 6}),
|
|
]
|
|
kalls2 = [call.foo(), call.bar(1)]
|
|
kalls2.extend(call.spam().baz(a=3).call_list())
|
|
kalls2.extend(call.bam(set(), foo={}).fish([1]).call_list())
|
|
|
|
mocks = []
|
|
for mock in Mock(), MagicMock():
|
|
mock(1, 2)
|
|
mock(a=3)
|
|
mock(3, 4)
|
|
mock(b=6)
|
|
mock(1, b=6)
|
|
mocks.append((mock, kalls1))
|
|
|
|
mock = Mock()
|
|
mock.foo()
|
|
mock.bar(1)
|
|
mock.spam().baz(a=3)
|
|
mock.bam(set(), foo={}).fish([1])
|
|
mocks.append((mock, kalls2))
|
|
|
|
for mock, kalls in mocks:
|
|
for i in range(len(kalls)):
|
|
for step in 1, 2, 3:
|
|
these = kalls[i:i+step]
|
|
mock.assert_has_calls(these)
|
|
|
|
if len(these) > 1:
|
|
self.assertRaises(
|
|
AssertionError,
|
|
mock.assert_has_calls,
|
|
list(reversed(these))
|
|
)
|
|
|
|
|
|
def test_assert_any_call(self):
|
|
mock = Mock()
|
|
mock(1, 2)
|
|
mock(a=3)
|
|
mock(1, b=6)
|
|
|
|
mock.assert_any_call(1, 2)
|
|
mock.assert_any_call(a=3)
|
|
mock.assert_any_call(1, b=6)
|
|
|
|
self.assertRaises(
|
|
AssertionError,
|
|
mock.assert_any_call
|
|
)
|
|
self.assertRaises(
|
|
AssertionError,
|
|
mock.assert_any_call,
|
|
1, 3
|
|
)
|
|
self.assertRaises(
|
|
AssertionError,
|
|
mock.assert_any_call,
|
|
a=4
|
|
)
|
|
|
|
|
|
def test_mock_calls_create_autospec(self):
|
|
def f(a, b):
|
|
pass
|
|
obj = Iter()
|
|
obj.f = f
|
|
|
|
funcs = [
|
|
create_autospec(f),
|
|
create_autospec(obj).f
|
|
]
|
|
for func in funcs:
|
|
func(1, 2)
|
|
func(3, 4)
|
|
|
|
self.assertEqual(
|
|
func.mock_calls, [call(1, 2), call(3, 4)]
|
|
)
|
|
|
|
|
|
def test_mock_add_spec(self):
|
|
class _One(object):
|
|
one = 1
|
|
class _Two(object):
|
|
two = 2
|
|
class Anything(object):
|
|
one = two = three = 'four'
|
|
|
|
klasses = [
|
|
Mock, MagicMock, NonCallableMock, NonCallableMagicMock
|
|
]
|
|
for Klass in list(klasses):
|
|
klasses.append(lambda K=Klass: K(spec=Anything))
|
|
klasses.append(lambda K=Klass: K(spec_set=Anything))
|
|
|
|
for Klass in klasses:
|
|
for kwargs in dict(), dict(spec_set=True):
|
|
mock = Klass()
|
|
#no error
|
|
mock.one, mock.two, mock.three
|
|
|
|
for One, Two in [(_One, _Two), (['one'], ['two'])]:
|
|
for kwargs in dict(), dict(spec_set=True):
|
|
mock.mock_add_spec(One, **kwargs)
|
|
|
|
mock.one
|
|
self.assertRaises(
|
|
AttributeError, getattr, mock, 'two'
|
|
)
|
|
self.assertRaises(
|
|
AttributeError, getattr, mock, 'three'
|
|
)
|
|
if 'spec_set' in kwargs:
|
|
self.assertRaises(
|
|
AttributeError, setattr, mock, 'three', None
|
|
)
|
|
|
|
mock.mock_add_spec(Two, **kwargs)
|
|
self.assertRaises(
|
|
AttributeError, getattr, mock, 'one'
|
|
)
|
|
mock.two
|
|
self.assertRaises(
|
|
AttributeError, getattr, mock, 'three'
|
|
)
|
|
if 'spec_set' in kwargs:
|
|
self.assertRaises(
|
|
AttributeError, setattr, mock, 'three', None
|
|
)
|
|
# note that creating a mock, setting an instance attribute, and
|
|
# *then* setting a spec doesn't work. Not the intended use case
|
|
|
|
|
|
def test_mock_add_spec_magic_methods(self):
|
|
for Klass in MagicMock, NonCallableMagicMock:
|
|
mock = Klass()
|
|
int(mock)
|
|
|
|
mock.mock_add_spec(object)
|
|
self.assertRaises(TypeError, int, mock)
|
|
|
|
mock = Klass()
|
|
mock['foo']
|
|
mock.__int__.return_value =4
|
|
|
|
mock.mock_add_spec(int)
|
|
self.assertEqual(int(mock), 4)
|
|
self.assertRaises(TypeError, lambda: mock['foo'])
|
|
|
|
|
|
def test_adding_child_mock(self):
|
|
for Klass in NonCallableMock, Mock, MagicMock, NonCallableMagicMock:
|
|
mock = Klass()
|
|
|
|
mock.foo = Mock()
|
|
mock.foo()
|
|
|
|
self.assertEqual(mock.method_calls, [call.foo()])
|
|
self.assertEqual(mock.mock_calls, [call.foo()])
|
|
|
|
mock = Klass()
|
|
mock.bar = Mock(name='name')
|
|
mock.bar()
|
|
self.assertEqual(mock.method_calls, [])
|
|
self.assertEqual(mock.mock_calls, [])
|
|
|
|
# mock with an existing _new_parent but no name
|
|
mock = Klass()
|
|
mock.baz = MagicMock()()
|
|
mock.baz()
|
|
self.assertEqual(mock.method_calls, [])
|
|
self.assertEqual(mock.mock_calls, [])
|
|
|
|
|
|
def test_adding_return_value_mock(self):
|
|
for Klass in Mock, MagicMock:
|
|
mock = Klass()
|
|
mock.return_value = MagicMock()
|
|
|
|
mock()()
|
|
self.assertEqual(mock.mock_calls, [call(), call()()])
|
|
|
|
|
|
def test_manager_mock(self):
|
|
class Foo(object):
|
|
one = 'one'
|
|
two = 'two'
|
|
manager = Mock()
|
|
p1 = patch.object(Foo, 'one')
|
|
p2 = patch.object(Foo, 'two')
|
|
|
|
mock_one = p1.start()
|
|
self.addCleanup(p1.stop)
|
|
mock_two = p2.start()
|
|
self.addCleanup(p2.stop)
|
|
|
|
manager.attach_mock(mock_one, 'one')
|
|
manager.attach_mock(mock_two, 'two')
|
|
|
|
Foo.two()
|
|
Foo.one()
|
|
|
|
self.assertEqual(manager.mock_calls, [call.two(), call.one()])
|
|
|
|
|
|
def test_magic_methods_mock_calls(self):
|
|
for Klass in Mock, MagicMock:
|
|
m = Klass()
|
|
m.__int__ = Mock(return_value=3)
|
|
m.__float__ = MagicMock(return_value=3.0)
|
|
int(m)
|
|
float(m)
|
|
|
|
self.assertEqual(m.mock_calls, [call.__int__(), call.__float__()])
|
|
self.assertEqual(m.method_calls, [])
|
|
|
|
|
|
def test_attribute_deletion(self):
|
|
# this behaviour isn't *useful*, but at least it's now tested...
|
|
for Klass in Mock, MagicMock, NonCallableMagicMock, NonCallableMock:
|
|
m = Klass()
|
|
original = m.foo
|
|
m.foo = 3
|
|
del m.foo
|
|
self.assertEqual(m.foo, original)
|
|
|
|
new = m.foo = Mock()
|
|
del m.foo
|
|
self.assertEqual(m.foo, new)
|
|
|
|
|
|
def test_mock_parents(self):
|
|
for Klass in Mock, MagicMock:
|
|
m = Klass()
|
|
original_repr = repr(m)
|
|
m.return_value = m
|
|
self.assertIs(m(), m)
|
|
self.assertEqual(repr(m), original_repr)
|
|
|
|
m.reset_mock()
|
|
self.assertIs(m(), m)
|
|
self.assertEqual(repr(m), original_repr)
|
|
|
|
m = Klass()
|
|
m.b = m.a
|
|
self.assertIn("name='mock.a'", repr(m.b))
|
|
self.assertIn("name='mock.a'", repr(m.a))
|
|
m.reset_mock()
|
|
self.assertIn("name='mock.a'", repr(m.b))
|
|
self.assertIn("name='mock.a'", repr(m.a))
|
|
|
|
m = Klass()
|
|
original_repr = repr(m)
|
|
m.a = m()
|
|
m.a.return_value = m
|
|
|
|
self.assertEqual(repr(m), original_repr)
|
|
self.assertEqual(repr(m.a()), original_repr)
|
|
|
|
|
|
def test_attach_mock(self):
|
|
classes = Mock, MagicMock, NonCallableMagicMock, NonCallableMock
|
|
for Klass in classes:
|
|
for Klass2 in classes:
|
|
m = Klass()
|
|
|
|
m2 = Klass2(name='foo')
|
|
m.attach_mock(m2, 'bar')
|
|
|
|
self.assertIs(m.bar, m2)
|
|
self.assertIn("name='mock.bar'", repr(m2))
|
|
|
|
m.bar.baz(1)
|
|
self.assertEqual(m.mock_calls, [call.bar.baz(1)])
|
|
self.assertEqual(m.method_calls, [call.bar.baz(1)])
|
|
|
|
|
|
def test_attach_mock_return_value(self):
|
|
classes = Mock, MagicMock, NonCallableMagicMock, NonCallableMock
|
|
for Klass in Mock, MagicMock:
|
|
for Klass2 in classes:
|
|
m = Klass()
|
|
|
|
m2 = Klass2(name='foo')
|
|
m.attach_mock(m2, 'return_value')
|
|
|
|
self.assertIs(m(), m2)
|
|
self.assertIn("name='mock()'", repr(m2))
|
|
|
|
m2.foo()
|
|
self.assertEqual(m.mock_calls, call().foo().call_list())
|
|
|
|
|
|
def test_attribute_deletion(self):
|
|
for mock in Mock(), MagicMock():
|
|
self.assertTrue(hasattr(mock, 'm'))
|
|
|
|
del mock.m
|
|
self.assertFalse(hasattr(mock, 'm'))
|
|
|
|
del mock.f
|
|
self.assertFalse(hasattr(mock, 'f'))
|
|
self.assertRaises(AttributeError, getattr, mock, 'f')
|
|
|
|
|
|
def test_class_assignable(self):
|
|
for mock in Mock(), MagicMock():
|
|
self.assertNotIsInstance(mock, int)
|
|
|
|
mock.__class__ = int
|
|
self.assertIsInstance(mock, int)
|
|
|
|
|
|
@unittest2.expectedFailure
|
|
def test_pickle(self):
|
|
for Klass in (MagicMock, Mock, Subclass, NonCallableMagicMock):
|
|
mock = Klass(name='foo', attribute=3)
|
|
mock.foo(1, 2, 3)
|
|
data = pickle.dumps(mock)
|
|
new = pickle.loads(data)
|
|
|
|
new.foo.assert_called_once_with(1, 2, 3)
|
|
self.assertFalse(new.called)
|
|
self.assertTrue(is_instance(new, Klass))
|
|
self.assertIsInstance(new, Thing)
|
|
self.assertIn('name="foo"', repr(new))
|
|
self.assertEqual(new.attribute, 3)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest2.main()
|