| # 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/ |
| |
| import os |
| import sys |
| |
| import unittest |
| from unittest.test.testmock import support |
| from unittest.test.testmock.support import SomeClass, is_instance |
| |
| from unittest.mock import ( |
| NonCallableMock, CallableMixin, patch, sentinel, |
| MagicMock, Mock, NonCallableMagicMock, patch, _patch, |
| DEFAULT, call, _get_target |
| ) |
| |
| |
| builtin_string = 'builtins' |
| |
| PTModule = sys.modules[__name__] |
| MODNAME = '%s.PTModule' % __name__ |
| |
| |
| def _get_proxy(obj, get_only=True): |
| class Proxy(object): |
| def __getattr__(self, name): |
| return getattr(obj, name) |
| if not get_only: |
| def __setattr__(self, name, value): |
| setattr(obj, name, value) |
| def __delattr__(self, name): |
| delattr(obj, name) |
| Proxy.__setattr__ = __setattr__ |
| Proxy.__delattr__ = __delattr__ |
| return Proxy() |
| |
| |
| # for use in the test |
| something = sentinel.Something |
| something_else = sentinel.SomethingElse |
| |
| |
| class Foo(object): |
| def __init__(self, a): |
| pass |
| def f(self, a): |
| pass |
| def g(self): |
| pass |
| foo = 'bar' |
| |
| class Bar(object): |
| def a(self): |
| pass |
| |
| foo_name = '%s.Foo' % __name__ |
| |
| |
| def function(a, b=Foo): |
| pass |
| |
| |
| 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(unittest.TestCase): |
| |
| def assertNotCallable(self, obj, magic=True): |
| MockClass = NonCallableMagicMock |
| if not magic: |
| MockClass = NonCallableMock |
| |
| self.assertRaises(TypeError, obj) |
| self.assertTrue(is_instance(obj, MockClass)) |
| self.assertFalse(is_instance(obj, CallableMixin)) |
| |
| |
| def test_single_patchobject(self): |
| class Something(object): |
| attribute = sentinel.Original |
| |
| @patch.object(Something, 'attribute', sentinel.Patched) |
| def test(): |
| self.assertEqual(Something.attribute, sentinel.Patched, "unpatched") |
| |
| test() |
| self.assertEqual(Something.attribute, sentinel.Original, |
| "patch not restored") |
| |
| |
| def test_patchobject_with_none(self): |
| class Something(object): |
| attribute = sentinel.Original |
| |
| @patch.object(Something, 'attribute', None) |
| def test(): |
| self.assertIsNone(Something.attribute, "unpatched") |
| |
| test() |
| self.assertEqual(Something.attribute, sentinel.Original, |
| "patch not restored") |
| |
| |
| def test_multiple_patchobject(self): |
| class Something(object): |
| attribute = sentinel.Original |
| next_attribute = sentinel.Original2 |
| |
| @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") |
| |
| test() |
| self.assertEqual(Something.attribute, sentinel.Original, |
| "patch not restored") |
| self.assertEqual(Something.next_attribute, sentinel.Original2, |
| "patch not restored") |
| |
| |
| def test_object_lookup_is_quite_lazy(self): |
| global something |
| original = something |
| @patch('%s.something' % __name__, sentinel.Something2) |
| def test(): |
| pass |
| |
| try: |
| something = sentinel.replacement_value |
| test() |
| self.assertEqual(something, sentinel.replacement_value) |
| finally: |
| something = original |
| |
| |
| def test_patch(self): |
| @patch('%s.something' % __name__, sentinel.Something2) |
| def test(): |
| self.assertEqual(PTModule.something, sentinel.Something2, |
| "unpatched") |
| |
| test() |
| self.assertEqual(PTModule.something, sentinel.Something, |
| "patch not restored") |
| |
| @patch('%s.something' % __name__, sentinel.Something2) |
| @patch('%s.something_else' % __name__, 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.assertNotEqual(open, mock, "patch not restored") |
| |
| |
| def test_patch_class_attribute(self): |
| @patch('%s.SomeClass.class_attribute' % __name__, |
| sentinel.ClassAttribute) |
| def test(): |
| self.assertEqual(PTModule.SomeClass.class_attribute, |
| sentinel.ClassAttribute, "unpatched") |
| test() |
| |
| self.assertIsNone(PTModule.SomeClass.class_attribute, |
| "patch not restored") |
| |
| |
| def test_patchobject_with_default_mock(self): |
| class Test(object): |
| something = sentinel.Original |
| something2 = sentinel.Original2 |
| |
| @patch.object(Test, 'something') |
| def test(mock): |
| self.assertEqual(mock, Test.something, |
| "Mock not passed into test function") |
| self.assertIsInstance(mock, MagicMock, |
| "patch with two arguments did not create a mock") |
| |
| test() |
| |
| @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.assertIsInstance(mock2, MagicMock, |
| "patch with two arguments did not create a mock") |
| self.assertIsInstance(mock2, MagicMock, |
| "patch with two arguments did not create a mock") |
| |
| # A hack to test that new mocks are passed the second time |
| self.assertNotEqual(outerMock1, mock1, "unexpected value for mock1") |
| self.assertNotEqual(outerMock2, mock2, "unexpected value for mock1") |
| return mock1, mock2 |
| |
| outerMock1 = outerMock2 = None |
| outerMock1, outerMock2 = test(sentinel.this1, sentinel.this2) |
| |
| # Test that executing a second time creates new mocks |
| test(sentinel.this1, sentinel.this2) |
| |
| |
| def test_patch_with_spec(self): |
| @patch('%s.SomeClass' % __name__, spec=SomeClass) |
| def test(MockSomeClass): |
| self.assertEqual(SomeClass, MockSomeClass) |
| self.assertTrue(is_instance(SomeClass.wibble, MagicMock)) |
| self.assertRaises(AttributeError, lambda: SomeClass.not_wibble) |
| |
| test() |
| |
| |
| def test_patchobject_with_spec(self): |
| @patch.object(SomeClass, 'class_attribute', spec=SomeClass) |
| def test(MockAttribute): |
| self.assertEqual(SomeClass.class_attribute, MockAttribute) |
| self.assertTrue(is_instance(SomeClass.class_attribute.wibble, |
| MagicMock)) |
| self.assertRaises(AttributeError, |
| lambda: SomeClass.class_attribute.not_wibble) |
| |
| test() |
| |
| |
| def test_patch_with_spec_as_list(self): |
| @patch('%s.SomeClass' % __name__, spec=['wibble']) |
| def test(MockSomeClass): |
| self.assertEqual(SomeClass, MockSomeClass) |
| self.assertTrue(is_instance(SomeClass.wibble, MagicMock)) |
| self.assertRaises(AttributeError, lambda: SomeClass.not_wibble) |
| |
| test() |
| |
| |
| def test_patchobject_with_spec_as_list(self): |
| @patch.object(SomeClass, 'class_attribute', spec=['wibble']) |
| def test(MockAttribute): |
| self.assertEqual(SomeClass.class_attribute, MockAttribute) |
| self.assertTrue(is_instance(SomeClass.class_attribute.wibble, |
| MagicMock)) |
| self.assertRaises(AttributeError, |
| lambda: SomeClass.class_attribute.not_wibble) |
| |
| test() |
| |
| |
| def test_nested_patch_with_spec_as_list(self): |
| # regression test for nested decorators |
| @patch('%s.open' % builtin_string) |
| @patch('%s.SomeClass' % __name__, spec=['wibble']) |
| def test(MockSomeClass, MockOpen): |
| self.assertEqual(SomeClass, MockSomeClass) |
| self.assertTrue(is_instance(SomeClass.wibble, MagicMock)) |
| self.assertRaises(AttributeError, lambda: SomeClass.not_wibble) |
| test() |
| |
| |
| def test_patch_with_spec_as_boolean(self): |
| @patch('%s.SomeClass' % __name__, spec=True) |
| def test(MockSomeClass): |
| self.assertEqual(SomeClass, MockSomeClass) |
| # Should not raise attribute error |
| MockSomeClass.wibble |
| |
| self.assertRaises(AttributeError, lambda: MockSomeClass.not_wibble) |
| |
| test() |
| |
| |
| def test_patch_object_with_spec_as_boolean(self): |
| @patch.object(PTModule, 'SomeClass', spec=True) |
| def test(MockSomeClass): |
| self.assertEqual(SomeClass, MockSomeClass) |
| # Should not raise attribute error |
| MockSomeClass.wibble |
| |
| self.assertRaises(AttributeError, lambda: MockSomeClass.not_wibble) |
| |
| test() |
| |
| |
| def test_patch_class_acts_with_spec_is_inherited(self): |
| @patch('%s.SomeClass' % __name__, spec=True) |
| def test(MockSomeClass): |
| self.assertTrue(is_instance(MockSomeClass, MagicMock)) |
| instance = MockSomeClass() |
| self.assertNotCallable(instance) |
| # Should not raise attribute error |
| instance.wibble |
| |
| self.assertRaises(AttributeError, lambda: instance.not_wibble) |
| |
| test() |
| |
| |
| def test_patch_with_create_mocks_non_existent_attributes(self): |
| @patch('%s.frooble' % builtin_string, sentinel.Frooble, create=True) |
| def test(): |
| self.assertEqual(frooble, sentinel.Frooble) |
| |
| test() |
| self.assertRaises(NameError, lambda: frooble) |
| |
| |
| def test_patchobject_with_create_mocks_non_existent_attributes(self): |
| @patch.object(SomeClass, 'frooble', sentinel.Frooble, create=True) |
| def test(): |
| self.assertEqual(SomeClass.frooble, sentinel.Frooble) |
| |
| test() |
| self.assertFalse(hasattr(SomeClass, 'frooble')) |
| |
| |
| def test_patch_wont_create_by_default(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 test_patchobject_wont_create_by_default(self): |
| try: |
| @patch.object(SomeClass, 'frooble', sentinel.Frooble) |
| def test(): |
| self.fail('Patching non existent attributes should fail') |
| |
| test() |
| except AttributeError: |
| pass |
| else: |
| self.fail('Patching non existent attributes should fail') |
| self.assertFalse(hasattr(SomeClass, 'frooble')) |
| |
| |
| def test_patch_with_static_methods(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 test_patch_local(self): |
| foo = sentinel.Foo |
| @patch.object(sentinel, 'Foo', 'Foo') |
| def anonymous(): |
| self.assertEqual(sentinel.Foo, 'Foo') |
| anonymous() |
| |
| self.assertEqual(sentinel.Foo, foo) |
| |
| |
| def test_patch_slots(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 test_patchobject_class_decorator(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 test_patch_class_decorator(self): |
| class Something(object): |
| attribute = sentinel.Original |
| |
| class Foo(object): |
| def test_method(other_self, mock_something): |
| self.assertEqual(PTModule.something, mock_something, |
| "unpatched") |
| def not_test_method(other_self): |
| self.assertEqual(PTModule.something, sentinel.Something, |
| "non-test method patched") |
| Foo = patch('%s.something' % __name__)(Foo) |
| |
| f = Foo() |
| f.test_method() |
| f.not_test_method() |
| |
| self.assertEqual(Something.attribute, sentinel.Original, |
| "patch not restored") |
| self.assertEqual(PTModule.something, sentinel.Something, |
| "patch not restored") |
| |
| |
| def test_patchobject_twice(self): |
| class Something(object): |
| attribute = sentinel.Original |
| next_attribute = sentinel.Original2 |
| |
| @patch.object(Something, 'attribute', sentinel.Patched) |
| @patch.object(Something, 'attribute', sentinel.Patched) |
| def test(): |
| self.assertEqual(Something.attribute, sentinel.Patched, "unpatched") |
| |
| test() |
| |
| self.assertEqual(Something.attribute, sentinel.Original, |
| "patch not restored") |
| |
| |
| def test_patch_dict(self): |
| foo = {'initial': object(), 'other': 'something'} |
| original = foo.copy() |
| |
| @patch.dict(foo) |
| def test(): |
| foo['a'] = 3 |
| del foo['initial'] |
| foo['other'] = 'something else' |
| |
| test() |
| |
| self.assertEqual(foo, original) |
| |
| @patch.dict(foo, {'a': 'b'}) |
| def test(): |
| self.assertEqual(len(foo), 3) |
| self.assertEqual(foo['a'], 'b') |
| |
| test() |
| |
| self.assertEqual(foo, original) |
| |
| @patch.dict(foo, [('a', 'b')]) |
| def test(): |
| self.assertEqual(len(foo), 3) |
| self.assertEqual(foo['a'], 'b') |
| |
| test() |
| |
| self.assertEqual(foo, original) |
| |
| |
| def test_patch_dict_with_container_object(self): |
| foo = Container() |
| foo['initial'] = object() |
| foo['other'] = 'something' |
| |
| original = foo.values.copy() |
| |
| @patch.dict(foo) |
| def test(): |
| foo['a'] = 3 |
| del foo['initial'] |
| foo['other'] = 'something else' |
| |
| test() |
| |
| self.assertEqual(foo.values, original) |
| |
| @patch.dict(foo, {'a': 'b'}) |
| def test(): |
| self.assertEqual(len(foo.values), 3) |
| self.assertEqual(foo['a'], 'b') |
| |
| test() |
| |
| self.assertEqual(foo.values, original) |
| |
| |
| def test_patch_dict_with_clear(self): |
| foo = {'initial': object(), 'other': 'something'} |
| original = foo.copy() |
| |
| @patch.dict(foo, clear=True) |
| def test(): |
| self.assertEqual(foo, {}) |
| foo['a'] = 3 |
| foo['other'] = 'something else' |
| |
| test() |
| |
| self.assertEqual(foo, original) |
| |
| @patch.dict(foo, {'a': 'b'}, clear=True) |
| def test(): |
| self.assertEqual(foo, {'a': 'b'}) |
| |
| test() |
| |
| self.assertEqual(foo, original) |
| |
| @patch.dict(foo, [('a', 'b')], clear=True) |
| def test(): |
| self.assertEqual(foo, {'a': 'b'}) |
| |
| test() |
| |
| self.assertEqual(foo, original) |
| |
| |
| def test_patch_dict_with_container_object_and_clear(self): |
| foo = Container() |
| foo['initial'] = object() |
| foo['other'] = 'something' |
| |
| original = foo.values.copy() |
| |
| @patch.dict(foo, clear=True) |
| def test(): |
| self.assertEqual(foo.values, {}) |
| foo['a'] = 3 |
| foo['other'] = 'something else' |
| |
| test() |
| |
| self.assertEqual(foo.values, original) |
| |
| @patch.dict(foo, {'a': 'b'}, clear=True) |
| def test(): |
| self.assertEqual(foo.values, {'a': 'b'}) |
| |
| test() |
| |
| self.assertEqual(foo.values, original) |
| |
| |
| def test_name_preserved(self): |
| foo = {} |
| |
| @patch('%s.SomeClass' % __name__, object()) |
| @patch('%s.SomeClass' % __name__, object(), autospec=True) |
| @patch.object(SomeClass, object()) |
| @patch.dict(foo) |
| def some_name(): |
| pass |
| |
| self.assertEqual(some_name.__name__, 'some_name') |
| |
| |
| def test_patch_with_exception(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 test_patch_dict_with_string(self): |
| @patch.dict('os.environ', {'konrad_delong': 'some value'}) |
| def test(): |
| self.assertIn('konrad_delong', os.environ) |
| |
| test() |
| |
| |
| def test_patch_descriptor(self): |
| # would be some effort to fix this - we could special case the |
| # builtin descriptors: classmethod, property, staticmethod |
| return |
| 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() |
| |
| |
| def test_patch_spec_set(self): |
| @patch('%s.SomeClass' % __name__, spec=SomeClass, spec_set=True) |
| def test(MockClass): |
| MockClass.z = 'foo' |
| |
| self.assertRaises(AttributeError, test) |
| |
| @patch.object(support, 'SomeClass', spec=SomeClass, spec_set=True) |
| def test(MockClass): |
| MockClass.z = 'foo' |
| |
| self.assertRaises(AttributeError, test) |
| @patch('%s.SomeClass' % __name__, spec_set=True) |
| def test(MockClass): |
| MockClass.z = 'foo' |
| |
| self.assertRaises(AttributeError, test) |
| |
| @patch.object(support, 'SomeClass', spec_set=True) |
| def test(MockClass): |
| MockClass.z = 'foo' |
| |
| self.assertRaises(AttributeError, test) |
| |
| |
| def test_spec_set_inherit(self): |
| @patch('%s.SomeClass' % __name__, spec_set=True) |
| def test(MockClass): |
| instance = MockClass() |
| instance.z = 'foo' |
| |
| self.assertRaises(AttributeError, test) |
| |
| |
| def test_patch_start_stop(self): |
| original = something |
| patcher = patch('%s.something' % __name__) |
| self.assertIs(something, original) |
| mock = patcher.start() |
| try: |
| self.assertIsNot(mock, original) |
| self.assertIs(something, mock) |
| finally: |
| patcher.stop() |
| self.assertIs(something, original) |
| |
| |
| def test_stop_without_start(self): |
| patcher = patch(foo_name, 'bar', 3) |
| |
| # calling stop without start used to produce a very obscure error |
| self.assertRaises(RuntimeError, patcher.stop) |
| |
| |
| def test_patchobject_start_stop(self): |
| original = something |
| patcher = patch.object(PTModule, 'something', 'foo') |
| self.assertIs(something, original) |
| replaced = patcher.start() |
| try: |
| self.assertEqual(replaced, 'foo') |
| self.assertIs(something, replaced) |
| finally: |
| patcher.stop() |
| self.assertIs(something, original) |
| |
| |
| def test_patch_dict_start_stop(self): |
| d = {'foo': 'bar'} |
| original = d.copy() |
| patcher = patch.dict(d, [('spam', 'eggs')], clear=True) |
| self.assertEqual(d, original) |
| |
| patcher.start() |
| try: |
| self.assertEqual(d, {'spam': 'eggs'}) |
| finally: |
| patcher.stop() |
| self.assertEqual(d, original) |
| |
| |
| def test_patch_dict_class_decorator(self): |
| this = self |
| d = {'spam': 'eggs'} |
| original = d.copy() |
| |
| class Test(object): |
| def test_first(self): |
| this.assertEqual(d, {'foo': 'bar'}) |
| def test_second(self): |
| this.assertEqual(d, {'foo': 'bar'}) |
| |
| Test = patch.dict(d, {'foo': 'bar'}, clear=True)(Test) |
| self.assertEqual(d, original) |
| |
| test = Test() |
| |
| test.test_first() |
| self.assertEqual(d, original) |
| |
| test.test_second() |
| self.assertEqual(d, original) |
| |
| test = Test() |
| |
| test.test_first() |
| self.assertEqual(d, original) |
| |
| test.test_second() |
| self.assertEqual(d, original) |
| |
| |
| def test_get_only_proxy(self): |
| class Something(object): |
| foo = 'foo' |
| class SomethingElse: |
| foo = 'foo' |
| |
| for thing in Something, SomethingElse, Something(), SomethingElse: |
| proxy = _get_proxy(thing) |
| |
| @patch.object(proxy, 'foo', 'bar') |
| def test(): |
| self.assertEqual(proxy.foo, 'bar') |
| test() |
| self.assertEqual(proxy.foo, 'foo') |
| self.assertEqual(thing.foo, 'foo') |
| self.assertNotIn('foo', proxy.__dict__) |
| |
| |
| def test_get_set_delete_proxy(self): |
| class Something(object): |
| foo = 'foo' |
| class SomethingElse: |
| foo = 'foo' |
| |
| for thing in Something, SomethingElse, Something(), SomethingElse: |
| proxy = _get_proxy(Something, get_only=False) |
| |
| @patch.object(proxy, 'foo', 'bar') |
| def test(): |
| self.assertEqual(proxy.foo, 'bar') |
| test() |
| self.assertEqual(proxy.foo, 'foo') |
| self.assertEqual(thing.foo, 'foo') |
| self.assertNotIn('foo', proxy.__dict__) |
| |
| |
| def test_patch_keyword_args(self): |
| kwargs = {'side_effect': KeyError, 'foo.bar.return_value': 33, |
| 'foo': MagicMock()} |
| |
| patcher = patch(foo_name, **kwargs) |
| mock = patcher.start() |
| patcher.stop() |
| |
| self.assertRaises(KeyError, mock) |
| self.assertEqual(mock.foo.bar(), 33) |
| self.assertIsInstance(mock.foo, MagicMock) |
| |
| |
| def test_patch_object_keyword_args(self): |
| kwargs = {'side_effect': KeyError, 'foo.bar.return_value': 33, |
| 'foo': MagicMock()} |
| |
| patcher = patch.object(Foo, 'f', **kwargs) |
| mock = patcher.start() |
| patcher.stop() |
| |
| self.assertRaises(KeyError, mock) |
| self.assertEqual(mock.foo.bar(), 33) |
| self.assertIsInstance(mock.foo, MagicMock) |
| |
| |
| def test_patch_dict_keyword_args(self): |
| original = {'foo': 'bar'} |
| copy = original.copy() |
| |
| patcher = patch.dict(original, foo=3, bar=4, baz=5) |
| patcher.start() |
| |
| try: |
| self.assertEqual(original, dict(foo=3, bar=4, baz=5)) |
| finally: |
| patcher.stop() |
| |
| self.assertEqual(original, copy) |
| |
| |
| def test_autospec(self): |
| class Boo(object): |
| def __init__(self, a): |
| pass |
| def f(self, a): |
| pass |
| def g(self): |
| pass |
| foo = 'bar' |
| |
| class Bar(object): |
| def a(self): |
| pass |
| |
| def _test(mock): |
| mock(1) |
| mock.assert_called_with(1) |
| self.assertRaises(TypeError, mock) |
| |
| def _test2(mock): |
| mock.f(1) |
| mock.f.assert_called_with(1) |
| self.assertRaises(TypeError, mock.f) |
| |
| mock.g() |
| mock.g.assert_called_with() |
| self.assertRaises(TypeError, mock.g, 1) |
| |
| self.assertRaises(AttributeError, getattr, mock, 'h') |
| |
| mock.foo.lower() |
| mock.foo.lower.assert_called_with() |
| self.assertRaises(AttributeError, getattr, mock.foo, 'bar') |
| |
| mock.Bar() |
| mock.Bar.assert_called_with() |
| |
| mock.Bar.a() |
| mock.Bar.a.assert_called_with() |
| self.assertRaises(TypeError, mock.Bar.a, 1) |
| |
| mock.Bar().a() |
| mock.Bar().a.assert_called_with() |
| self.assertRaises(TypeError, mock.Bar().a, 1) |
| |
| self.assertRaises(AttributeError, getattr, mock.Bar, 'b') |
| self.assertRaises(AttributeError, getattr, mock.Bar(), 'b') |
| |
| def function(mock): |
| _test(mock) |
| _test2(mock) |
| _test2(mock(1)) |
| self.assertIs(mock, Foo) |
| return mock |
| |
| test = patch(foo_name, autospec=True)(function) |
| |
| mock = test() |
| self.assertIsNot(Foo, mock) |
| # test patching a second time works |
| test() |
| |
| module = sys.modules[__name__] |
| test = patch.object(module, 'Foo', autospec=True)(function) |
| |
| mock = test() |
| self.assertIsNot(Foo, mock) |
| # test patching a second time works |
| test() |
| |
| |
| def test_autospec_function(self): |
| @patch('%s.function' % __name__, autospec=True) |
| def test(mock): |
| function(1) |
| function.assert_called_with(1) |
| function(2, 3) |
| function.assert_called_with(2, 3) |
| |
| self.assertRaises(TypeError, function) |
| self.assertRaises(AttributeError, getattr, function, 'foo') |
| |
| test() |
| |
| |
| def test_autospec_keywords(self): |
| @patch('%s.function' % __name__, autospec=True, |
| return_value=3) |
| def test(mock_function): |
| #self.assertEqual(function.abc, 'foo') |
| return function(1, 2) |
| |
| result = test() |
| self.assertEqual(result, 3) |
| |
| |
| def test_autospec_with_new(self): |
| patcher = patch('%s.function' % __name__, new=3, autospec=True) |
| self.assertRaises(TypeError, patcher.start) |
| |
| module = sys.modules[__name__] |
| patcher = patch.object(module, 'function', new=3, autospec=True) |
| self.assertRaises(TypeError, patcher.start) |
| |
| |
| def test_autospec_with_object(self): |
| class Bar(Foo): |
| extra = [] |
| |
| patcher = patch(foo_name, autospec=Bar) |
| mock = patcher.start() |
| try: |
| self.assertIsInstance(mock, Bar) |
| self.assertIsInstance(mock.extra, list) |
| finally: |
| patcher.stop() |
| |
| |
| def test_autospec_inherits(self): |
| FooClass = Foo |
| patcher = patch(foo_name, autospec=True) |
| mock = patcher.start() |
| try: |
| self.assertIsInstance(mock, FooClass) |
| self.assertIsInstance(mock(3), FooClass) |
| finally: |
| patcher.stop() |
| |
| |
| def test_autospec_name(self): |
| patcher = patch(foo_name, autospec=True) |
| mock = patcher.start() |
| |
| try: |
| self.assertIn(" name='Foo'", repr(mock)) |
| self.assertIn(" name='Foo.f'", repr(mock.f)) |
| self.assertIn(" name='Foo()'", repr(mock(None))) |
| self.assertIn(" name='Foo().f'", repr(mock(None).f)) |
| finally: |
| patcher.stop() |
| |
| |
| def test_tracebacks(self): |
| @patch.object(Foo, 'f', object()) |
| def test(): |
| raise AssertionError |
| try: |
| test() |
| except: |
| err = sys.exc_info() |
| |
| result = unittest.TextTestResult(None, None, 0) |
| traceback = result._exc_info_to_string(err, self) |
| self.assertIn('raise AssertionError', traceback) |
| |
| |
| def test_new_callable_patch(self): |
| patcher = patch(foo_name, new_callable=NonCallableMagicMock) |
| |
| m1 = patcher.start() |
| patcher.stop() |
| m2 = patcher.start() |
| patcher.stop() |
| |
| self.assertIsNot(m1, m2) |
| for mock in m1, m2: |
| self.assertNotCallable(m1) |
| |
| |
| def test_new_callable_patch_object(self): |
| patcher = patch.object(Foo, 'f', new_callable=NonCallableMagicMock) |
| |
| m1 = patcher.start() |
| patcher.stop() |
| m2 = patcher.start() |
| patcher.stop() |
| |
| self.assertIsNot(m1, m2) |
| for mock in m1, m2: |
| self.assertNotCallable(m1) |
| |
| |
| def test_new_callable_keyword_arguments(self): |
| class Bar(object): |
| kwargs = None |
| def __init__(self, **kwargs): |
| Bar.kwargs = kwargs |
| |
| patcher = patch(foo_name, new_callable=Bar, arg1=1, arg2=2) |
| m = patcher.start() |
| try: |
| self.assertIs(type(m), Bar) |
| self.assertEqual(Bar.kwargs, dict(arg1=1, arg2=2)) |
| finally: |
| patcher.stop() |
| |
| |
| def test_new_callable_spec(self): |
| class Bar(object): |
| kwargs = None |
| def __init__(self, **kwargs): |
| Bar.kwargs = kwargs |
| |
| patcher = patch(foo_name, new_callable=Bar, spec=Bar) |
| patcher.start() |
| try: |
| self.assertEqual(Bar.kwargs, dict(spec=Bar)) |
| finally: |
| patcher.stop() |
| |
| patcher = patch(foo_name, new_callable=Bar, spec_set=Bar) |
| patcher.start() |
| try: |
| self.assertEqual(Bar.kwargs, dict(spec_set=Bar)) |
| finally: |
| patcher.stop() |
| |
| |
| def test_new_callable_create(self): |
| non_existent_attr = '%s.weeeee' % foo_name |
| p = patch(non_existent_attr, new_callable=NonCallableMock) |
| self.assertRaises(AttributeError, p.start) |
| |
| p = patch(non_existent_attr, new_callable=NonCallableMock, |
| create=True) |
| m = p.start() |
| try: |
| self.assertNotCallable(m, magic=False) |
| finally: |
| p.stop() |
| |
| |
| def test_new_callable_incompatible_with_new(self): |
| self.assertRaises( |
| ValueError, patch, foo_name, new=object(), new_callable=MagicMock |
| ) |
| self.assertRaises( |
| ValueError, patch.object, Foo, 'f', new=object(), |
| new_callable=MagicMock |
| ) |
| |
| |
| def test_new_callable_incompatible_with_autospec(self): |
| self.assertRaises( |
| ValueError, patch, foo_name, new_callable=MagicMock, |
| autospec=True |
| ) |
| self.assertRaises( |
| ValueError, patch.object, Foo, 'f', new_callable=MagicMock, |
| autospec=True |
| ) |
| |
| |
| def test_new_callable_inherit_for_mocks(self): |
| class MockSub(Mock): |
| pass |
| |
| MockClasses = ( |
| NonCallableMock, NonCallableMagicMock, MagicMock, Mock, MockSub |
| ) |
| for Klass in MockClasses: |
| for arg in 'spec', 'spec_set': |
| kwargs = {arg: True} |
| p = patch(foo_name, new_callable=Klass, **kwargs) |
| m = p.start() |
| try: |
| instance = m.return_value |
| self.assertRaises(AttributeError, getattr, instance, 'x') |
| finally: |
| p.stop() |
| |
| |
| def test_new_callable_inherit_non_mock(self): |
| class NotAMock(object): |
| def __init__(self, spec): |
| self.spec = spec |
| |
| p = patch(foo_name, new_callable=NotAMock, spec=True) |
| m = p.start() |
| try: |
| self.assertTrue(is_instance(m, NotAMock)) |
| self.assertRaises(AttributeError, getattr, m, 'return_value') |
| finally: |
| p.stop() |
| |
| self.assertEqual(m.spec, Foo) |
| |
| |
| def test_new_callable_class_decorating(self): |
| test = self |
| original = Foo |
| class SomeTest(object): |
| |
| def _test(self, mock_foo): |
| test.assertIsNot(Foo, original) |
| test.assertIs(Foo, mock_foo) |
| test.assertIsInstance(Foo, SomeClass) |
| |
| def test_two(self, mock_foo): |
| self._test(mock_foo) |
| def test_one(self, mock_foo): |
| self._test(mock_foo) |
| |
| SomeTest = patch(foo_name, new_callable=SomeClass)(SomeTest) |
| SomeTest().test_one() |
| SomeTest().test_two() |
| self.assertIs(Foo, original) |
| |
| |
| def test_patch_multiple(self): |
| original_foo = Foo |
| original_f = Foo.f |
| original_g = Foo.g |
| |
| patcher1 = patch.multiple(foo_name, f=1, g=2) |
| patcher2 = patch.multiple(Foo, f=1, g=2) |
| |
| for patcher in patcher1, patcher2: |
| patcher.start() |
| try: |
| self.assertIs(Foo, original_foo) |
| self.assertEqual(Foo.f, 1) |
| self.assertEqual(Foo.g, 2) |
| finally: |
| patcher.stop() |
| |
| self.assertIs(Foo, original_foo) |
| self.assertEqual(Foo.f, original_f) |
| self.assertEqual(Foo.g, original_g) |
| |
| |
| @patch.multiple(foo_name, f=3, g=4) |
| def test(): |
| self.assertIs(Foo, original_foo) |
| self.assertEqual(Foo.f, 3) |
| self.assertEqual(Foo.g, 4) |
| |
| test() |
| |
| |
| def test_patch_multiple_no_kwargs(self): |
| self.assertRaises(ValueError, patch.multiple, foo_name) |
| self.assertRaises(ValueError, patch.multiple, Foo) |
| |
| |
| def test_patch_multiple_create_mocks(self): |
| original_foo = Foo |
| original_f = Foo.f |
| original_g = Foo.g |
| |
| @patch.multiple(foo_name, f=DEFAULT, g=3, foo=DEFAULT) |
| def test(f, foo): |
| self.assertIs(Foo, original_foo) |
| self.assertIs(Foo.f, f) |
| self.assertEqual(Foo.g, 3) |
| self.assertIs(Foo.foo, foo) |
| self.assertTrue(is_instance(f, MagicMock)) |
| self.assertTrue(is_instance(foo, MagicMock)) |
| |
| test() |
| self.assertEqual(Foo.f, original_f) |
| self.assertEqual(Foo.g, original_g) |
| |
| |
| def test_patch_multiple_create_mocks_different_order(self): |
| # bug revealed by Jython! |
| original_f = Foo.f |
| original_g = Foo.g |
| |
| patcher = patch.object(Foo, 'f', 3) |
| patcher.attribute_name = 'f' |
| |
| other = patch.object(Foo, 'g', DEFAULT) |
| other.attribute_name = 'g' |
| patcher.additional_patchers = [other] |
| |
| @patcher |
| def test(g): |
| self.assertIs(Foo.g, g) |
| self.assertEqual(Foo.f, 3) |
| |
| test() |
| self.assertEqual(Foo.f, original_f) |
| self.assertEqual(Foo.g, original_g) |
| |
| |
| def test_patch_multiple_stacked_decorators(self): |
| original_foo = Foo |
| original_f = Foo.f |
| original_g = Foo.g |
| |
| @patch.multiple(foo_name, f=DEFAULT) |
| @patch.multiple(foo_name, foo=DEFAULT) |
| @patch(foo_name + '.g') |
| def test1(g, **kwargs): |
| _test(g, **kwargs) |
| |
| @patch.multiple(foo_name, f=DEFAULT) |
| @patch(foo_name + '.g') |
| @patch.multiple(foo_name, foo=DEFAULT) |
| def test2(g, **kwargs): |
| _test(g, **kwargs) |
| |
| @patch(foo_name + '.g') |
| @patch.multiple(foo_name, f=DEFAULT) |
| @patch.multiple(foo_name, foo=DEFAULT) |
| def test3(g, **kwargs): |
| _test(g, **kwargs) |
| |
| def _test(g, **kwargs): |
| f = kwargs.pop('f') |
| foo = kwargs.pop('foo') |
| self.assertFalse(kwargs) |
| |
| self.assertIs(Foo, original_foo) |
| self.assertIs(Foo.f, f) |
| self.assertIs(Foo.g, g) |
| self.assertIs(Foo.foo, foo) |
| self.assertTrue(is_instance(f, MagicMock)) |
| self.assertTrue(is_instance(g, MagicMock)) |
| self.assertTrue(is_instance(foo, MagicMock)) |
| |
| test1() |
| test2() |
| test3() |
| self.assertEqual(Foo.f, original_f) |
| self.assertEqual(Foo.g, original_g) |
| |
| |
| def test_patch_multiple_create_mocks_patcher(self): |
| original_foo = Foo |
| original_f = Foo.f |
| original_g = Foo.g |
| |
| patcher = patch.multiple(foo_name, f=DEFAULT, g=3, foo=DEFAULT) |
| |
| result = patcher.start() |
| try: |
| f = result['f'] |
| foo = result['foo'] |
| self.assertEqual(set(result), set(['f', 'foo'])) |
| |
| self.assertIs(Foo, original_foo) |
| self.assertIs(Foo.f, f) |
| self.assertIs(Foo.foo, foo) |
| self.assertTrue(is_instance(f, MagicMock)) |
| self.assertTrue(is_instance(foo, MagicMock)) |
| finally: |
| patcher.stop() |
| |
| self.assertEqual(Foo.f, original_f) |
| self.assertEqual(Foo.g, original_g) |
| |
| |
| def test_patch_multiple_decorating_class(self): |
| test = self |
| original_foo = Foo |
| original_f = Foo.f |
| original_g = Foo.g |
| |
| class SomeTest(object): |
| |
| def _test(self, f, foo): |
| test.assertIs(Foo, original_foo) |
| test.assertIs(Foo.f, f) |
| test.assertEqual(Foo.g, 3) |
| test.assertIs(Foo.foo, foo) |
| test.assertTrue(is_instance(f, MagicMock)) |
| test.assertTrue(is_instance(foo, MagicMock)) |
| |
| def test_two(self, f, foo): |
| self._test(f, foo) |
| def test_one(self, f, foo): |
| self._test(f, foo) |
| |
| SomeTest = patch.multiple( |
| foo_name, f=DEFAULT, g=3, foo=DEFAULT |
| )(SomeTest) |
| |
| thing = SomeTest() |
| thing.test_one() |
| thing.test_two() |
| |
| self.assertEqual(Foo.f, original_f) |
| self.assertEqual(Foo.g, original_g) |
| |
| |
| def test_patch_multiple_create(self): |
| patcher = patch.multiple(Foo, blam='blam') |
| self.assertRaises(AttributeError, patcher.start) |
| |
| patcher = patch.multiple(Foo, blam='blam', create=True) |
| patcher.start() |
| try: |
| self.assertEqual(Foo.blam, 'blam') |
| finally: |
| patcher.stop() |
| |
| self.assertFalse(hasattr(Foo, 'blam')) |
| |
| |
| def test_patch_multiple_spec_set(self): |
| # if spec_set works then we can assume that spec and autospec also |
| # work as the underlying machinery is the same |
| patcher = patch.multiple(Foo, foo=DEFAULT, spec_set=['a', 'b']) |
| result = patcher.start() |
| try: |
| self.assertEqual(Foo.foo, result['foo']) |
| Foo.foo.a(1) |
| Foo.foo.b(2) |
| Foo.foo.a.assert_called_with(1) |
| Foo.foo.b.assert_called_with(2) |
| self.assertRaises(AttributeError, setattr, Foo.foo, 'c', None) |
| finally: |
| patcher.stop() |
| |
| |
| def test_patch_multiple_new_callable(self): |
| class Thing(object): |
| pass |
| |
| patcher = patch.multiple( |
| Foo, f=DEFAULT, g=DEFAULT, new_callable=Thing |
| ) |
| result = patcher.start() |
| try: |
| self.assertIs(Foo.f, result['f']) |
| self.assertIs(Foo.g, result['g']) |
| self.assertIsInstance(Foo.f, Thing) |
| self.assertIsInstance(Foo.g, Thing) |
| self.assertIsNot(Foo.f, Foo.g) |
| finally: |
| patcher.stop() |
| |
| |
| def test_nested_patch_failure(self): |
| original_f = Foo.f |
| original_g = Foo.g |
| |
| @patch.object(Foo, 'g', 1) |
| @patch.object(Foo, 'missing', 1) |
| @patch.object(Foo, 'f', 1) |
| def thing1(): |
| pass |
| |
| @patch.object(Foo, 'missing', 1) |
| @patch.object(Foo, 'g', 1) |
| @patch.object(Foo, 'f', 1) |
| def thing2(): |
| pass |
| |
| @patch.object(Foo, 'g', 1) |
| @patch.object(Foo, 'f', 1) |
| @patch.object(Foo, 'missing', 1) |
| def thing3(): |
| pass |
| |
| for func in thing1, thing2, thing3: |
| self.assertRaises(AttributeError, func) |
| self.assertEqual(Foo.f, original_f) |
| self.assertEqual(Foo.g, original_g) |
| |
| |
| def test_new_callable_failure(self): |
| original_f = Foo.f |
| original_g = Foo.g |
| original_foo = Foo.foo |
| |
| def crasher(): |
| raise NameError('crasher') |
| |
| @patch.object(Foo, 'g', 1) |
| @patch.object(Foo, 'foo', new_callable=crasher) |
| @patch.object(Foo, 'f', 1) |
| def thing1(): |
| pass |
| |
| @patch.object(Foo, 'foo', new_callable=crasher) |
| @patch.object(Foo, 'g', 1) |
| @patch.object(Foo, 'f', 1) |
| def thing2(): |
| pass |
| |
| @patch.object(Foo, 'g', 1) |
| @patch.object(Foo, 'f', 1) |
| @patch.object(Foo, 'foo', new_callable=crasher) |
| def thing3(): |
| pass |
| |
| for func in thing1, thing2, thing3: |
| self.assertRaises(NameError, func) |
| self.assertEqual(Foo.f, original_f) |
| self.assertEqual(Foo.g, original_g) |
| self.assertEqual(Foo.foo, original_foo) |
| |
| |
| def test_patch_multiple_failure(self): |
| original_f = Foo.f |
| original_g = Foo.g |
| |
| patcher = patch.object(Foo, 'f', 1) |
| patcher.attribute_name = 'f' |
| |
| good = patch.object(Foo, 'g', 1) |
| good.attribute_name = 'g' |
| |
| bad = patch.object(Foo, 'missing', 1) |
| bad.attribute_name = 'missing' |
| |
| for additionals in [good, bad], [bad, good]: |
| patcher.additional_patchers = additionals |
| |
| @patcher |
| def func(): |
| pass |
| |
| self.assertRaises(AttributeError, func) |
| self.assertEqual(Foo.f, original_f) |
| self.assertEqual(Foo.g, original_g) |
| |
| |
| def test_patch_multiple_new_callable_failure(self): |
| original_f = Foo.f |
| original_g = Foo.g |
| original_foo = Foo.foo |
| |
| def crasher(): |
| raise NameError('crasher') |
| |
| patcher = patch.object(Foo, 'f', 1) |
| patcher.attribute_name = 'f' |
| |
| good = patch.object(Foo, 'g', 1) |
| good.attribute_name = 'g' |
| |
| bad = patch.object(Foo, 'foo', new_callable=crasher) |
| bad.attribute_name = 'foo' |
| |
| for additionals in [good, bad], [bad, good]: |
| patcher.additional_patchers = additionals |
| |
| @patcher |
| def func(): |
| pass |
| |
| self.assertRaises(NameError, func) |
| self.assertEqual(Foo.f, original_f) |
| self.assertEqual(Foo.g, original_g) |
| self.assertEqual(Foo.foo, original_foo) |
| |
| |
| def test_patch_multiple_string_subclasses(self): |
| Foo = type('Foo', (str,), {'fish': 'tasty'}) |
| foo = Foo() |
| @patch.multiple(foo, fish='nearly gone') |
| def test(): |
| self.assertEqual(foo.fish, 'nearly gone') |
| |
| test() |
| self.assertEqual(foo.fish, 'tasty') |
| |
| |
| @patch('unittest.mock.patch.TEST_PREFIX', 'foo') |
| def test_patch_test_prefix(self): |
| class Foo(object): |
| thing = 'original' |
| |
| def foo_one(self): |
| return self.thing |
| def foo_two(self): |
| return self.thing |
| def test_one(self): |
| return self.thing |
| def test_two(self): |
| return self.thing |
| |
| Foo = patch.object(Foo, 'thing', 'changed')(Foo) |
| |
| foo = Foo() |
| self.assertEqual(foo.foo_one(), 'changed') |
| self.assertEqual(foo.foo_two(), 'changed') |
| self.assertEqual(foo.test_one(), 'original') |
| self.assertEqual(foo.test_two(), 'original') |
| |
| |
| @patch('unittest.mock.patch.TEST_PREFIX', 'bar') |
| def test_patch_dict_test_prefix(self): |
| class Foo(object): |
| def bar_one(self): |
| return dict(the_dict) |
| def bar_two(self): |
| return dict(the_dict) |
| def test_one(self): |
| return dict(the_dict) |
| def test_two(self): |
| return dict(the_dict) |
| |
| the_dict = {'key': 'original'} |
| Foo = patch.dict(the_dict, key='changed')(Foo) |
| |
| foo =Foo() |
| self.assertEqual(foo.bar_one(), {'key': 'changed'}) |
| self.assertEqual(foo.bar_two(), {'key': 'changed'}) |
| self.assertEqual(foo.test_one(), {'key': 'original'}) |
| self.assertEqual(foo.test_two(), {'key': 'original'}) |
| |
| |
| def test_patch_with_spec_mock_repr(self): |
| for arg in ('spec', 'autospec', 'spec_set'): |
| p = patch('%s.SomeClass' % __name__, **{arg: True}) |
| m = p.start() |
| try: |
| self.assertIn(" name='SomeClass'", repr(m)) |
| self.assertIn(" name='SomeClass.class_attribute'", |
| repr(m.class_attribute)) |
| self.assertIn(" name='SomeClass()'", repr(m())) |
| self.assertIn(" name='SomeClass().class_attribute'", |
| repr(m().class_attribute)) |
| finally: |
| p.stop() |
| |
| |
| def test_patch_nested_autospec_repr(self): |
| with patch('unittest.test.testmock.support', autospec=True) as m: |
| self.assertIn(" name='support.SomeClass.wibble()'", |
| repr(m.SomeClass.wibble())) |
| self.assertIn(" name='support.SomeClass().wibble()'", |
| repr(m.SomeClass().wibble())) |
| |
| |
| |
| def test_mock_calls_with_patch(self): |
| for arg in ('spec', 'autospec', 'spec_set'): |
| p = patch('%s.SomeClass' % __name__, **{arg: True}) |
| m = p.start() |
| try: |
| m.wibble() |
| |
| kalls = [call.wibble()] |
| self.assertEqual(m.mock_calls, kalls) |
| self.assertEqual(m.method_calls, kalls) |
| self.assertEqual(m.wibble.mock_calls, [call()]) |
| |
| result = m() |
| kalls.append(call()) |
| self.assertEqual(m.mock_calls, kalls) |
| |
| result.wibble() |
| kalls.append(call().wibble()) |
| self.assertEqual(m.mock_calls, kalls) |
| |
| self.assertEqual(result.mock_calls, [call.wibble()]) |
| self.assertEqual(result.wibble.mock_calls, [call()]) |
| self.assertEqual(result.method_calls, [call.wibble()]) |
| finally: |
| p.stop() |
| |
| |
| def test_patch_imports_lazily(self): |
| sys.modules.pop('squizz', None) |
| |
| p1 = patch('squizz.squozz') |
| self.assertRaises(ImportError, p1.start) |
| |
| squizz = Mock() |
| squizz.squozz = 6 |
| sys.modules['squizz'] = squizz |
| p1 = patch('squizz.squozz') |
| squizz.squozz = 3 |
| p1.start() |
| p1.stop() |
| self.assertEqual(squizz.squozz, 3) |
| |
| |
| def test_patch_propogrates_exc_on_exit(self): |
| class holder: |
| exc_info = None, None, None |
| |
| class custom_patch(_patch): |
| def __exit__(self, etype=None, val=None, tb=None): |
| _patch.__exit__(self, etype, val, tb) |
| holder.exc_info = etype, val, tb |
| stop = __exit__ |
| |
| def with_custom_patch(target): |
| getter, attribute = _get_target(target) |
| return custom_patch( |
| getter, attribute, DEFAULT, None, False, None, |
| None, None, {} |
| ) |
| |
| @with_custom_patch('squizz.squozz') |
| def test(mock): |
| raise RuntimeError |
| |
| self.assertRaises(RuntimeError, test) |
| self.assertIs(holder.exc_info[0], RuntimeError) |
| self.assertIsNotNone(holder.exc_info[1], |
| 'exception value not propgated') |
| self.assertIsNotNone(holder.exc_info[2], |
| 'exception traceback not propgated') |
| |
| |
| def test_create_and_specs(self): |
| for kwarg in ('spec', 'spec_set', 'autospec'): |
| p = patch('%s.doesnotexist' % __name__, create=True, |
| **{kwarg: True}) |
| self.assertRaises(TypeError, p.start) |
| self.assertRaises(NameError, lambda: doesnotexist) |
| |
| # check that spec with create is innocuous if the original exists |
| p = patch(MODNAME, create=True, **{kwarg: True}) |
| p.start() |
| p.stop() |
| |
| |
| def test_multiple_specs(self): |
| original = PTModule |
| for kwarg in ('spec', 'spec_set'): |
| p = patch(MODNAME, autospec=0, **{kwarg: 0}) |
| self.assertRaises(TypeError, p.start) |
| self.assertIs(PTModule, original) |
| |
| for kwarg in ('spec', 'autospec'): |
| p = patch(MODNAME, spec_set=0, **{kwarg: 0}) |
| self.assertRaises(TypeError, p.start) |
| self.assertIs(PTModule, original) |
| |
| for kwarg in ('spec_set', 'autospec'): |
| p = patch(MODNAME, spec=0, **{kwarg: 0}) |
| self.assertRaises(TypeError, p.start) |
| self.assertIs(PTModule, original) |
| |
| |
| def test_specs_false_instead_of_none(self): |
| p = patch(MODNAME, spec=False, spec_set=False, autospec=False) |
| mock = p.start() |
| try: |
| # no spec should have been set, so attribute access should not fail |
| mock.does_not_exist |
| mock.does_not_exist = 3 |
| finally: |
| p.stop() |
| |
| |
| def test_falsey_spec(self): |
| for kwarg in ('spec', 'autospec', 'spec_set'): |
| p = patch(MODNAME, **{kwarg: 0}) |
| m = p.start() |
| try: |
| self.assertRaises(AttributeError, getattr, m, 'doesnotexit') |
| finally: |
| p.stop() |
| |
| |
| def test_spec_set_true(self): |
| for kwarg in ('spec', 'autospec'): |
| p = patch(MODNAME, spec_set=True, **{kwarg: True}) |
| m = p.start() |
| try: |
| self.assertRaises(AttributeError, setattr, m, |
| 'doesnotexist', 'something') |
| self.assertRaises(AttributeError, getattr, m, 'doesnotexist') |
| finally: |
| p.stop() |
| |
| |
| def test_callable_spec_as_list(self): |
| spec = ('__call__',) |
| p = patch(MODNAME, spec=spec) |
| m = p.start() |
| try: |
| self.assertTrue(callable(m)) |
| finally: |
| p.stop() |
| |
| |
| def test_not_callable_spec_as_list(self): |
| spec = ('foo', 'bar') |
| p = patch(MODNAME, spec=spec) |
| m = p.start() |
| try: |
| self.assertFalse(callable(m)) |
| finally: |
| p.stop() |
| |
| |
| |
| if __name__ == '__main__': |
| unittest.main() |