diff options
Diffstat (limited to 'Lib/unittest/test')
| -rw-r--r-- | Lib/unittest/test/__init__.py | 1 | ||||
| -rw-r--r-- | Lib/unittest/test/_test_warnings.py | 1 | ||||
| -rw-r--r-- | Lib/unittest/test/test_assertions.py | 73 | ||||
| -rw-r--r-- | Lib/unittest/test/test_case.py | 63 | ||||
| -rw-r--r-- | Lib/unittest/test/test_loader.py | 4 | ||||
| -rw-r--r-- | Lib/unittest/test/test_program.py | 17 | ||||
| -rw-r--r-- | Lib/unittest/test/testmock/__init__.py | 17 | ||||
| -rw-r--r-- | Lib/unittest/test/testmock/support.py | 23 | ||||
| -rw-r--r-- | Lib/unittest/test/testmock/testcallable.py | 147 | ||||
| -rw-r--r-- | Lib/unittest/test/testmock/testhelpers.py | 889 | ||||
| -rw-r--r-- | Lib/unittest/test/testmock/testmagicmethods.py | 403 | ||||
| -rw-r--r-- | Lib/unittest/test/testmock/testmock.py | 1275 | ||||
| -rw-r--r-- | Lib/unittest/test/testmock/testpatch.py | 1785 | ||||
| -rw-r--r-- | Lib/unittest/test/testmock/testsentinel.py | 28 | ||||
| -rw-r--r-- | Lib/unittest/test/testmock/testwith.py | 176 | 
15 files changed, 4873 insertions, 29 deletions
diff --git a/Lib/unittest/test/__init__.py b/Lib/unittest/test/__init__.py index 99b730b..cdae8a7 100644 --- a/Lib/unittest/test/__init__.py +++ b/Lib/unittest/test/__init__.py @@ -14,6 +14,7 @@ def suite():              __import__(modname)              module = sys.modules[modname]              suite.addTest(loader.loadTestsFromModule(module)) +    suite.addTest(loader.loadTestsFromName('unittest.test.testmock'))      return suite diff --git a/Lib/unittest/test/_test_warnings.py b/Lib/unittest/test/_test_warnings.py index d0be18d..5cbfb53 100644 --- a/Lib/unittest/test/_test_warnings.py +++ b/Lib/unittest/test/_test_warnings.py @@ -10,7 +10,6 @@ combinations of warnings args and -W flags and check that the output is correct.  See #10535.  """ -import io  import sys  import unittest  import warnings diff --git a/Lib/unittest/test/test_assertions.py b/Lib/unittest/test/test_assertions.py index a1d20eb..d43fe5a 100644 --- a/Lib/unittest/test/test_assertions.py +++ b/Lib/unittest/test/test_assertions.py @@ -1,6 +1,7 @@  import datetime  import warnings  import unittest +from itertools import product  class Test_Assertions(unittest.TestCase): @@ -145,6 +146,14 @@ class TestLongMessage(unittest.TestCase):          self.testableTrue._formatMessage(one, '\uFFFD')      def assertMessages(self, methodName, args, errors): +        """ +        Check that methodName(*args) raises the correct error messages. +        errors should be a list of 4 regex that match the error when: +          1) longMessage = False and no msg passed; +          2) longMessage = False and msg passed; +          3) longMessage = True and no msg passed; +          4) longMessage = True and msg passed; +        """          def getMethod(i):              useTestableFalse  = i < 2              if useTestableFalse: @@ -284,3 +293,67 @@ class TestLongMessage(unittest.TestCase):                              ["^unexpectedly identical: None$", "^oops$",                               "^unexpectedly identical: None$",                               "^unexpectedly identical: None : oops$"]) + + +    def assertMessagesCM(self, methodName, args, func, errors): +        """ +        Check that the correct error messages are raised while executing: +          with method(*args): +              func() +        *errors* should be a list of 4 regex that match the error when: +          1) longMessage = False and no msg passed; +          2) longMessage = False and msg passed; +          3) longMessage = True and no msg passed; +          4) longMessage = True and msg passed; +        """ +        p = product((self.testableFalse, self.testableTrue), +                    ({}, {"msg": "oops"})) +        for (cls, kwargs), err in zip(p, errors): +            method = getattr(cls, methodName) +            with self.assertRaisesRegex(cls.failureException, err): +                with method(*args, **kwargs) as cm: +                    func() + +    def testAssertRaises(self): +        self.assertMessagesCM('assertRaises', (TypeError,), lambda: None, +                              ['^TypeError not raised$', '^oops$', +                               '^TypeError not raised$', +                               '^TypeError not raised : oops$']) + +    def testAssertRaisesRegex(self): +        # test error not raised +        self.assertMessagesCM('assertRaisesRegex', (TypeError, 'unused regex'), +                              lambda: None, +                              ['^TypeError not raised$', '^oops$', +                               '^TypeError not raised$', +                               '^TypeError not raised : oops$']) +        # test error raised but with wrong message +        def raise_wrong_message(): +            raise TypeError('foo') +        self.assertMessagesCM('assertRaisesRegex', (TypeError, 'regex'), +                              raise_wrong_message, +                              ['^"regex" does not match "foo"$', '^oops$', +                               '^"regex" does not match "foo"$', +                               '^"regex" does not match "foo" : oops$']) + +    def testAssertWarns(self): +        self.assertMessagesCM('assertWarns', (UserWarning,), lambda: None, +                              ['^UserWarning not triggered$', '^oops$', +                               '^UserWarning not triggered$', +                               '^UserWarning not triggered : oops$']) + +    def testAssertWarnsRegex(self): +        # test error not raised +        self.assertMessagesCM('assertWarnsRegex', (UserWarning, 'unused regex'), +                              lambda: None, +                              ['^UserWarning not triggered$', '^oops$', +                               '^UserWarning not triggered$', +                               '^UserWarning not triggered : oops$']) +        # test warning raised but with wrong message +        def raise_wrong_message(): +            warnings.warn('foo') +        self.assertMessagesCM('assertWarnsRegex', (UserWarning, 'regex'), +                              raise_wrong_message, +                              ['^"regex" does not match "foo"$', '^oops$', +                               '^"regex" does not match "foo"$', +                               '^"regex" does not match "foo" : oops$']) diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py index c74a539..fdb2e78 100644 --- a/Lib/unittest/test/test_case.py +++ b/Lib/unittest/test/test_case.py @@ -4,6 +4,7 @@ import pickle  import re  import sys  import warnings +import weakref  import inspect  from copy import deepcopy @@ -386,27 +387,62 @@ class Test_TestCase(unittest.TestCase, TestEquality, TestHashing):          self.assertIsInstance(Foo().id(), str) -    # "If result is omitted or None, a temporary result object is created -    # and used, but is not made available to the caller. As TestCase owns the +    # "If result is omitted or None, a temporary result object is created, +    # used, and is made available to the caller. As TestCase owns the      # temporary result startTestRun and stopTestRun are called.      def test_run__uses_defaultTestResult(self):          events = [] +        defaultResult = LoggingResult(events)          class Foo(unittest.TestCase):              def test(self):                  events.append('test')              def defaultTestResult(self): -                return LoggingResult(events) +                return defaultResult          # Make run() find a result object on its own -        Foo('test').run() +        result = Foo('test').run() +        self.assertIs(result, defaultResult)          expected = ['startTestRun', 'startTest', 'test', 'addSuccess',              'stopTest', 'stopTestRun']          self.assertEqual(events, expected) + +    # "The result object is returned to run's caller" +    def test_run__returns_given_result(self): + +        class Foo(unittest.TestCase): +            def test(self): +                pass + +        result = unittest.TestResult() + +        retval = Foo('test').run(result) +        self.assertIs(retval, result) + + +    # "The same effect [as method run] may be had by simply calling the +    # TestCase instance." +    def test_call__invoking_an_instance_delegates_to_run(self): +        resultIn = unittest.TestResult() +        resultOut = unittest.TestResult() + +        class Foo(unittest.TestCase): +            def test(self): +                pass + +            def run(self, result): +                self.assertIs(result, resultIn) +                return resultOut + +        retval = Foo('test')(resultIn) + +        self.assertIs(retval, resultOut) + +      def testShortDescriptionWithoutDocstring(self):          self.assertIsNone(self.shortDescription()) @@ -1140,7 +1176,6 @@ test case              (self.assert_, (True,)),              (self.failUnlessRaises, (TypeError, lambda _: 3.14 + 'spam')),              (self.failIf, (False,)), -            (self.assertSameElements, ([1, 1, 2, 3], [1, 2, 3])),              (self.assertDictContainsSubset, (dict(a=1, b=2), dict(a=1, b=2, c=3))),              (self.assertRaisesRegexp, (KeyError, 'foo', lambda: {}['foo'])),              (self.assertRegexpMatches, ('bar', 'bar')), @@ -1149,18 +1184,20 @@ test case              with self.assertWarns(DeprecationWarning):                  meth(*args) -    def testDeprecatedFailMethods(self): -        """Test that the deprecated fail* methods get removed in 3.3""" +    # disable this test for now. When the version where the fail* methods will +    # be removed is decided, re-enable it and update the version +    def _testDeprecatedFailMethods(self): +        """Test that the deprecated fail* methods get removed in 3.x"""          if sys.version_info[:2] < (3, 3):              return          deprecated_names = [              'failIfEqual', 'failUnlessEqual', 'failUnlessAlmostEqual',              'failIfAlmostEqual', 'failUnless', 'failUnlessRaises', 'failIf', -            'assertSameElements', 'assertDictContainsSubset', +            'assertDictContainsSubset',          ]          for deprecated_name in deprecated_names:              with self.assertRaises(AttributeError): -                getattr(self, deprecated_name)  # remove these in 3.3 +                getattr(self, deprecated_name)  # remove these in 3.x      def testDeepcopy(self):          # Issue: 5660 @@ -1268,3 +1305,11 @@ test case              klass('test_something').run(result)              self.assertEqual(len(result.errors), 1)              self.assertEqual(result.testsRun, 1) + +    @support.cpython_only +    def testNoCycles(self): +        case = unittest.TestCase() +        wr = weakref.ref(case) +        with support.disable_gc(): +            del case +            self.assertFalse(wr()) diff --git a/Lib/unittest/test/test_loader.py b/Lib/unittest/test/test_loader.py index f7e31a5..d1b9ef5 100644 --- a/Lib/unittest/test/test_loader.py +++ b/Lib/unittest/test/test_loader.py @@ -239,7 +239,7 @@ class Test_TestLoader(unittest.TestCase):          try:              loader.loadTestsFromName('sdasfasfasdf')          except ImportError as e: -            self.assertEqual(str(e), "No module named sdasfasfasdf") +            self.assertEqual(str(e), "No module named 'sdasfasfasdf'")          else:              self.fail("TestLoader.loadTestsFromName failed to raise ImportError") @@ -619,7 +619,7 @@ class Test_TestLoader(unittest.TestCase):          try:              loader.loadTestsFromNames(['sdasfasfasdf'])          except ImportError as e: -            self.assertEqual(str(e), "No module named sdasfasfasdf") +            self.assertEqual(str(e), "No module named 'sdasfasfasdf'")          else:              self.fail("TestLoader.loadTestsFromNames failed to raise ImportError") diff --git a/Lib/unittest/test/test_program.py b/Lib/unittest/test/test_program.py index d5d0f5a..9794868 100644 --- a/Lib/unittest/test/test_program.py +++ b/Lib/unittest/test/test_program.py @@ -131,23 +131,6 @@ class TestCommandLineArgs(unittest.TestCase):          FakeRunner.test = None          FakeRunner.raiseError = False -    def testHelpAndUnknown(self): -        program = self.program -        def usageExit(msg=None): -            program.msg = msg -            program.exit = True -        program.usageExit = usageExit - -        for opt in '-h', '-H', '--help': -            program.exit = False -            program.parseArgs([None, opt]) -            self.assertTrue(program.exit) -            self.assertIsNone(program.msg) - -        program.parseArgs([None, '-$']) -        self.assertTrue(program.exit) -        self.assertIsNotNone(program.msg) -      def testVerbosity(self):          program = self.program diff --git a/Lib/unittest/test/testmock/__init__.py b/Lib/unittest/test/testmock/__init__.py new file mode 100644 index 0000000..87d7ae9 --- /dev/null +++ b/Lib/unittest/test/testmock/__init__.py @@ -0,0 +1,17 @@ +import os +import sys +import unittest + + +here = os.path.dirname(__file__) +loader = unittest.defaultTestLoader + +def load_tests(*args): +    suite = unittest.TestSuite() +    for fn in os.listdir(here): +        if fn.startswith("test") and fn.endswith(".py"): +            modname = "unittest.test.testmock." + fn[:-3] +            __import__(modname) +            module = sys.modules[modname] +            suite.addTest(loader.loadTestsFromModule(module)) +    return suite diff --git a/Lib/unittest/test/testmock/support.py b/Lib/unittest/test/testmock/support.py new file mode 100644 index 0000000..f473879 --- /dev/null +++ b/Lib/unittest/test/testmock/support.py @@ -0,0 +1,23 @@ +import sys + +def is_instance(obj, klass): +    """Version of is_instance that doesn't access __class__""" +    return issubclass(type(obj), klass) + + +class SomeClass(object): +    class_attribute = None + +    def wibble(self): +        pass + + +class X(object): +    pass + + +def examine_warnings(func): +    def wrapper(): +        with catch_warnings(record=True) as ws: +            func(ws) +    return wrapper diff --git a/Lib/unittest/test/testmock/testcallable.py b/Lib/unittest/test/testmock/testcallable.py new file mode 100644 index 0000000..7b2dd00 --- /dev/null +++ b/Lib/unittest/test/testmock/testcallable.py @@ -0,0 +1,147 @@ +# 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 unittest +from unittest.test.testmock.support import is_instance, X, SomeClass + +from unittest.mock import ( +    Mock, MagicMock, NonCallableMagicMock, +    NonCallableMock, patch, create_autospec, +    CallableMixin +) + + + +class TestCallable(unittest.TestCase): + +    def assertNotCallable(self, mock): +        self.assertTrue(is_instance(mock, NonCallableMagicMock)) +        self.assertFalse(is_instance(mock, CallableMixin)) + + +    def test_non_callable(self): +        for mock in NonCallableMagicMock(), NonCallableMock(): +            self.assertRaises(TypeError, mock) +            self.assertFalse(hasattr(mock, '__call__')) +            self.assertIn(mock.__class__.__name__, repr(mock)) + + +    def test_heirarchy(self): +        self.assertTrue(issubclass(MagicMock, Mock)) +        self.assertTrue(issubclass(NonCallableMagicMock, NonCallableMock)) + + +    def test_attributes(self): +        one = NonCallableMock() +        self.assertTrue(issubclass(type(one.one), Mock)) + +        two = NonCallableMagicMock() +        self.assertTrue(issubclass(type(two.two), MagicMock)) + + +    def test_subclasses(self): +        class MockSub(Mock): +            pass + +        one = MockSub() +        self.assertTrue(issubclass(type(one.one), MockSub)) + +        class MagicSub(MagicMock): +            pass + +        two = MagicSub() +        self.assertTrue(issubclass(type(two.two), MagicSub)) + + +    def test_patch_spec(self): +        patcher = patch('%s.X' % __name__, spec=True) +        mock = patcher.start() +        self.addCleanup(patcher.stop) + +        instance = mock() +        mock.assert_called_once_with() + +        self.assertNotCallable(instance) +        self.assertRaises(TypeError, instance) + + +    def test_patch_spec_set(self): +        patcher = patch('%s.X' % __name__, spec_set=True) +        mock = patcher.start() +        self.addCleanup(patcher.stop) + +        instance = mock() +        mock.assert_called_once_with() + +        self.assertNotCallable(instance) +        self.assertRaises(TypeError, instance) + + +    def test_patch_spec_instance(self): +        patcher = patch('%s.X' % __name__, spec=X()) +        mock = patcher.start() +        self.addCleanup(patcher.stop) + +        self.assertNotCallable(mock) +        self.assertRaises(TypeError, mock) + + +    def test_patch_spec_set_instance(self): +        patcher = patch('%s.X' % __name__, spec_set=X()) +        mock = patcher.start() +        self.addCleanup(patcher.stop) + +        self.assertNotCallable(mock) +        self.assertRaises(TypeError, mock) + + +    def test_patch_spec_callable_class(self): +        class CallableX(X): +            def __call__(self): +                pass + +        class Sub(CallableX): +            pass + +        class Multi(SomeClass, Sub): +            pass + +        for arg in 'spec', 'spec_set': +            for Klass in CallableX, Sub, Multi: +                with patch('%s.X' % __name__, **{arg: Klass}) as mock: +                    instance = mock() +                    mock.assert_called_once_with() + +                    self.assertTrue(is_instance(instance, MagicMock)) +                    # inherited spec +                    self.assertRaises(AttributeError, getattr, instance, +                                      'foobarbaz') + +                    result = instance() +                    # instance is callable, result has no spec +                    instance.assert_called_once_with() + +                    result(3, 2, 1) +                    result.assert_called_once_with(3, 2, 1) +                    result.foo(3, 2, 1) +                    result.foo.assert_called_once_with(3, 2, 1) + + +    def test_create_autopsec(self): +        mock = create_autospec(X) +        instance = mock() +        self.assertRaises(TypeError, instance) + +        mock = create_autospec(X()) +        self.assertRaises(TypeError, mock) + + +    def test_create_autospec_instance(self): +        mock = create_autospec(SomeClass, instance=True) + +        self.assertRaises(TypeError, mock) +        mock.wibble() +        mock.wibble.assert_called_once_with() + +        self.assertRaises(TypeError, mock.wibble, 'some',  'args') diff --git a/Lib/unittest/test/testmock/testhelpers.py b/Lib/unittest/test/testmock/testhelpers.py new file mode 100644 index 0000000..8bfb293 --- /dev/null +++ b/Lib/unittest/test/testmock/testhelpers.py @@ -0,0 +1,889 @@ +import unittest + +from unittest.mock import ( +    call, _Call, create_autospec, MagicMock, +    Mock, ANY, _CallList, patch, PropertyMock +) + +from datetime import datetime + +class SomeClass(object): +    def one(self, a, b): +        pass +    def two(self): +        pass +    def three(self, a=None): +        pass + + + +class AnyTest(unittest.TestCase): + +    def test_any(self): +        self.assertEqual(ANY, object()) + +        mock = Mock() +        mock(ANY) +        mock.assert_called_with(ANY) + +        mock = Mock() +        mock(foo=ANY) +        mock.assert_called_with(foo=ANY) + +    def test_repr(self): +        self.assertEqual(repr(ANY), '<ANY>') +        self.assertEqual(str(ANY), '<ANY>') + + +    def test_any_and_datetime(self): +        mock = Mock() +        mock(datetime.now(), foo=datetime.now()) + +        mock.assert_called_with(ANY, foo=ANY) + + +    def test_any_mock_calls_comparison_order(self): +        mock = Mock() +        d = datetime.now() +        class Foo(object): +            def __eq__(self, other): +                return False +            def __ne__(self, other): +                return True + +        for d in datetime.now(), Foo(): +            mock.reset_mock() + +            mock(d, foo=d, bar=d) +            mock.method(d, zinga=d, alpha=d) +            mock().method(a1=d, z99=d) + +            expected = [ +                call(ANY, foo=ANY, bar=ANY), +                call.method(ANY, zinga=ANY, alpha=ANY), +                call(), call().method(a1=ANY, z99=ANY) +            ] +            self.assertEqual(expected, mock.mock_calls) +            self.assertEqual(mock.mock_calls, expected) + + + +class CallTest(unittest.TestCase): + +    def test_call_with_call(self): +        kall = _Call() +        self.assertEqual(kall, _Call()) +        self.assertEqual(kall, _Call(('',))) +        self.assertEqual(kall, _Call(((),))) +        self.assertEqual(kall, _Call(({},))) +        self.assertEqual(kall, _Call(('', ()))) +        self.assertEqual(kall, _Call(('', {}))) +        self.assertEqual(kall, _Call(('', (), {}))) +        self.assertEqual(kall, _Call(('foo',))) +        self.assertEqual(kall, _Call(('bar', ()))) +        self.assertEqual(kall, _Call(('baz', {}))) +        self.assertEqual(kall, _Call(('spam', (), {}))) + +        kall = _Call(((1, 2, 3),)) +        self.assertEqual(kall, _Call(((1, 2, 3),))) +        self.assertEqual(kall, _Call(('', (1, 2, 3)))) +        self.assertEqual(kall, _Call(((1, 2, 3), {}))) +        self.assertEqual(kall, _Call(('', (1, 2, 3), {}))) + +        kall = _Call(((1, 2, 4),)) +        self.assertNotEqual(kall, _Call(('', (1, 2, 3)))) +        self.assertNotEqual(kall, _Call(('', (1, 2, 3), {}))) + +        kall = _Call(('foo', (1, 2, 4),)) +        self.assertNotEqual(kall, _Call(('', (1, 2, 4)))) +        self.assertNotEqual(kall, _Call(('', (1, 2, 4), {}))) +        self.assertNotEqual(kall, _Call(('bar', (1, 2, 4)))) +        self.assertNotEqual(kall, _Call(('bar', (1, 2, 4), {}))) + +        kall = _Call(({'a': 3},)) +        self.assertEqual(kall, _Call(('', (), {'a': 3}))) +        self.assertEqual(kall, _Call(('', {'a': 3}))) +        self.assertEqual(kall, _Call(((), {'a': 3}))) +        self.assertEqual(kall, _Call(({'a': 3},))) + + +    def test_empty__Call(self): +        args = _Call() + +        self.assertEqual(args, ()) +        self.assertEqual(args, ('foo',)) +        self.assertEqual(args, ((),)) +        self.assertEqual(args, ('foo', ())) +        self.assertEqual(args, ('foo',(), {})) +        self.assertEqual(args, ('foo', {})) +        self.assertEqual(args, ({},)) + + +    def test_named_empty_call(self): +        args = _Call(('foo', (), {})) + +        self.assertEqual(args, ('foo',)) +        self.assertEqual(args, ('foo', ())) +        self.assertEqual(args, ('foo',(), {})) +        self.assertEqual(args, ('foo', {})) + +        self.assertNotEqual(args, ((),)) +        self.assertNotEqual(args, ()) +        self.assertNotEqual(args, ({},)) +        self.assertNotEqual(args, ('bar',)) +        self.assertNotEqual(args, ('bar', ())) +        self.assertNotEqual(args, ('bar', {})) + + +    def test_call_with_args(self): +        args = _Call(((1, 2, 3), {})) + +        self.assertEqual(args, ((1, 2, 3),)) +        self.assertEqual(args, ('foo', (1, 2, 3))) +        self.assertEqual(args, ('foo', (1, 2, 3), {})) +        self.assertEqual(args, ((1, 2, 3), {})) + + +    def test_named_call_with_args(self): +        args = _Call(('foo', (1, 2, 3), {})) + +        self.assertEqual(args, ('foo', (1, 2, 3))) +        self.assertEqual(args, ('foo', (1, 2, 3), {})) + +        self.assertNotEqual(args, ((1, 2, 3),)) +        self.assertNotEqual(args, ((1, 2, 3), {})) + + +    def test_call_with_kwargs(self): +        args = _Call(((), dict(a=3, b=4))) + +        self.assertEqual(args, (dict(a=3, b=4),)) +        self.assertEqual(args, ('foo', dict(a=3, b=4))) +        self.assertEqual(args, ('foo', (), dict(a=3, b=4))) +        self.assertEqual(args, ((), dict(a=3, b=4))) + + +    def test_named_call_with_kwargs(self): +        args = _Call(('foo', (), dict(a=3, b=4))) + +        self.assertEqual(args, ('foo', dict(a=3, b=4))) +        self.assertEqual(args, ('foo', (), dict(a=3, b=4))) + +        self.assertNotEqual(args, (dict(a=3, b=4),)) +        self.assertNotEqual(args, ((), dict(a=3, b=4))) + + +    def test_call_with_args_call_empty_name(self): +        args = _Call(((1, 2, 3), {})) +        self.assertEqual(args, call(1, 2, 3)) +        self.assertEqual(call(1, 2, 3), args) +        self.assertTrue(call(1, 2, 3) in [args]) + + +    def test_call_ne(self): +        self.assertNotEqual(_Call(((1, 2, 3),)), call(1, 2)) +        self.assertFalse(_Call(((1, 2, 3),)) != call(1, 2, 3)) +        self.assertTrue(_Call(((1, 2), {})) != call(1, 2, 3)) + + +    def test_call_non_tuples(self): +        kall = _Call(((1, 2, 3),)) +        for value in 1, None, self, int: +            self.assertNotEqual(kall, value) +            self.assertFalse(kall == value) + + +    def test_repr(self): +        self.assertEqual(repr(_Call()), 'call()') +        self.assertEqual(repr(_Call(('foo',))), 'call.foo()') + +        self.assertEqual(repr(_Call(((1, 2, 3), {'a': 'b'}))), +                         "call(1, 2, 3, a='b')") +        self.assertEqual(repr(_Call(('bar', (1, 2, 3), {'a': 'b'}))), +                         "call.bar(1, 2, 3, a='b')") + +        self.assertEqual(repr(call), 'call') +        self.assertEqual(str(call), 'call') + +        self.assertEqual(repr(call()), 'call()') +        self.assertEqual(repr(call(1)), 'call(1)') +        self.assertEqual(repr(call(zz='thing')), "call(zz='thing')") + +        self.assertEqual(repr(call().foo), 'call().foo') +        self.assertEqual(repr(call(1).foo.bar(a=3).bing), +                         'call().foo.bar().bing') +        self.assertEqual( +            repr(call().foo(1, 2, a=3)), +            "call().foo(1, 2, a=3)" +        ) +        self.assertEqual(repr(call()()), "call()()") +        self.assertEqual(repr(call(1)(2)), "call()(2)") +        self.assertEqual( +            repr(call()().bar().baz.beep(1)), +            "call()().bar().baz.beep(1)" +        ) + + +    def test_call(self): +        self.assertEqual(call(), ('', (), {})) +        self.assertEqual(call('foo', 'bar', one=3, two=4), +                         ('', ('foo', 'bar'), {'one': 3, 'two': 4})) + +        mock = Mock() +        mock(1, 2, 3) +        mock(a=3, b=6) +        self.assertEqual(mock.call_args_list, +                         [call(1, 2, 3), call(a=3, b=6)]) + +    def test_attribute_call(self): +        self.assertEqual(call.foo(1), ('foo', (1,), {})) +        self.assertEqual(call.bar.baz(fish='eggs'), +                         ('bar.baz', (), {'fish': 'eggs'})) + +        mock = Mock() +        mock.foo(1, 2 ,3) +        mock.bar.baz(a=3, b=6) +        self.assertEqual(mock.method_calls, +                         [call.foo(1, 2, 3), call.bar.baz(a=3, b=6)]) + + +    def test_extended_call(self): +        result = call(1).foo(2).bar(3, a=4) +        self.assertEqual(result, ('().foo().bar', (3,), dict(a=4))) + +        mock = MagicMock() +        mock(1, 2, a=3, b=4) +        self.assertEqual(mock.call_args, call(1, 2, a=3, b=4)) +        self.assertNotEqual(mock.call_args, call(1, 2, 3)) + +        self.assertEqual(mock.call_args_list, [call(1, 2, a=3, b=4)]) +        self.assertEqual(mock.mock_calls, [call(1, 2, a=3, b=4)]) + +        mock = MagicMock() +        mock.foo(1).bar()().baz.beep(a=6) + +        last_call = call.foo(1).bar()().baz.beep(a=6) +        self.assertEqual(mock.mock_calls[-1], last_call) +        self.assertEqual(mock.mock_calls, last_call.call_list()) + + +    def test_call_list(self): +        mock = MagicMock() +        mock(1) +        self.assertEqual(call(1).call_list(), mock.mock_calls) + +        mock = MagicMock() +        mock(1).method(2) +        self.assertEqual(call(1).method(2).call_list(), +                         mock.mock_calls) + +        mock = MagicMock() +        mock(1).method(2)(3) +        self.assertEqual(call(1).method(2)(3).call_list(), +                         mock.mock_calls) + +        mock = MagicMock() +        int(mock(1).method(2)(3).foo.bar.baz(4)(5)) +        kall = call(1).method(2)(3).foo.bar.baz(4)(5).__int__() +        self.assertEqual(kall.call_list(), mock.mock_calls) + + +    def test_call_any(self): +        self.assertEqual(call, ANY) + +        m = MagicMock() +        int(m) +        self.assertEqual(m.mock_calls, [ANY]) +        self.assertEqual([ANY], m.mock_calls) + + +    def test_two_args_call(self): +        args = _Call(((1, 2), {'a': 3}), two=True) +        self.assertEqual(len(args), 2) +        self.assertEqual(args[0], (1, 2)) +        self.assertEqual(args[1], {'a': 3}) + +        other_args = _Call(((1, 2), {'a': 3})) +        self.assertEqual(args, other_args) + + +class SpecSignatureTest(unittest.TestCase): + +    def _check_someclass_mock(self, mock): +        self.assertRaises(AttributeError, getattr, mock, 'foo') +        mock.one(1, 2) +        mock.one.assert_called_with(1, 2) +        self.assertRaises(AssertionError, +                          mock.one.assert_called_with, 3, 4) +        self.assertRaises(TypeError, mock.one, 1) + +        mock.two() +        mock.two.assert_called_with() +        self.assertRaises(AssertionError, +                          mock.two.assert_called_with, 3) +        self.assertRaises(TypeError, mock.two, 1) + +        mock.three() +        mock.three.assert_called_with() +        self.assertRaises(AssertionError, +                          mock.three.assert_called_with, 3) +        self.assertRaises(TypeError, mock.three, 3, 2) + +        mock.three(1) +        mock.three.assert_called_with(1) + +        mock.three(a=1) +        mock.three.assert_called_with(a=1) + + +    def test_basic(self): +        for spec in (SomeClass, SomeClass()): +            mock = create_autospec(spec) +            self._check_someclass_mock(mock) + + +    def test_create_autospec_return_value(self): +        def f(): +            pass +        mock = create_autospec(f, return_value='foo') +        self.assertEqual(mock(), 'foo') + +        class Foo(object): +            pass + +        mock = create_autospec(Foo, return_value='foo') +        self.assertEqual(mock(), 'foo') + + +    def test_autospec_reset_mock(self): +        m = create_autospec(int) +        int(m) +        m.reset_mock() +        self.assertEqual(m.__int__.call_count, 0) + + +    def test_mocking_unbound_methods(self): +        class Foo(object): +            def foo(self, foo): +                pass +        p = patch.object(Foo, 'foo') +        mock_foo = p.start() +        Foo().foo(1) + +        mock_foo.assert_called_with(1) + + +    def test_create_autospec_unbound_methods(self): +        # see mock issue 128 +        # this is expected to fail until the issue is fixed +        return +        class Foo(object): +            def foo(self): +                pass + +        klass = create_autospec(Foo) +        instance = klass() +        self.assertRaises(TypeError, instance.foo, 1) + +        # Note: no type checking on the "self" parameter +        klass.foo(1) +        klass.foo.assert_called_with(1) +        self.assertRaises(TypeError, klass.foo) + + +    def test_create_autospec_keyword_arguments(self): +        class Foo(object): +            a = 3 +        m = create_autospec(Foo, a='3') +        self.assertEqual(m.a, '3') + + +    def test_create_autospec_keyword_only_arguments(self): +        def foo(a, *, b=None): +            pass + +        m = create_autospec(foo) +        m(1) +        m.assert_called_with(1) +        self.assertRaises(TypeError, m, 1, 2) + +        m(2, b=3) +        m.assert_called_with(2, b=3) + + +    def test_function_as_instance_attribute(self): +        obj = SomeClass() +        def f(a): +            pass +        obj.f = f + +        mock = create_autospec(obj) +        mock.f('bing') +        mock.f.assert_called_with('bing') + + +    def test_spec_as_list(self): +        # because spec as a list of strings in the mock constructor means +        # something very different we treat a list instance as the type. +        mock = create_autospec([]) +        mock.append('foo') +        mock.append.assert_called_with('foo') + +        self.assertRaises(AttributeError, getattr, mock, 'foo') + +        class Foo(object): +            foo = [] + +        mock = create_autospec(Foo) +        mock.foo.append(3) +        mock.foo.append.assert_called_with(3) +        self.assertRaises(AttributeError, getattr, mock.foo, 'foo') + + +    def test_attributes(self): +        class Sub(SomeClass): +            attr = SomeClass() + +        sub_mock = create_autospec(Sub) + +        for mock in (sub_mock, sub_mock.attr): +            self._check_someclass_mock(mock) + + +    def test_builtin_functions_types(self): +        # we could replace builtin functions / methods with a function +        # with *args / **kwargs signature. Using the builtin method type +        # as a spec seems to work fairly well though. +        class BuiltinSubclass(list): +            def bar(self, arg): +                pass +            sorted = sorted +            attr = {} + +        mock = create_autospec(BuiltinSubclass) +        mock.append(3) +        mock.append.assert_called_with(3) +        self.assertRaises(AttributeError, getattr, mock.append, 'foo') + +        mock.bar('foo') +        mock.bar.assert_called_with('foo') +        self.assertRaises(TypeError, mock.bar, 'foo', 'bar') +        self.assertRaises(AttributeError, getattr, mock.bar, 'foo') + +        mock.sorted([1, 2]) +        mock.sorted.assert_called_with([1, 2]) +        self.assertRaises(AttributeError, getattr, mock.sorted, 'foo') + +        mock.attr.pop(3) +        mock.attr.pop.assert_called_with(3) +        self.assertRaises(AttributeError, getattr, mock.attr, 'foo') + + +    def test_method_calls(self): +        class Sub(SomeClass): +            attr = SomeClass() + +        mock = create_autospec(Sub) +        mock.one(1, 2) +        mock.two() +        mock.three(3) + +        expected = [call.one(1, 2), call.two(), call.three(3)] +        self.assertEqual(mock.method_calls, expected) + +        mock.attr.one(1, 2) +        mock.attr.two() +        mock.attr.three(3) + +        expected.extend( +            [call.attr.one(1, 2), call.attr.two(), call.attr.three(3)] +        ) +        self.assertEqual(mock.method_calls, expected) + + +    def test_magic_methods(self): +        class BuiltinSubclass(list): +            attr = {} + +        mock = create_autospec(BuiltinSubclass) +        self.assertEqual(list(mock), []) +        self.assertRaises(TypeError, int, mock) +        self.assertRaises(TypeError, int, mock.attr) +        self.assertEqual(list(mock), []) + +        self.assertIsInstance(mock['foo'], MagicMock) +        self.assertIsInstance(mock.attr['foo'], MagicMock) + + +    def test_spec_set(self): +        class Sub(SomeClass): +            attr = SomeClass() + +        for spec in (Sub, Sub()): +            mock = create_autospec(spec, spec_set=True) +            self._check_someclass_mock(mock) + +            self.assertRaises(AttributeError, setattr, mock, 'foo', 'bar') +            self.assertRaises(AttributeError, setattr, mock.attr, 'foo', 'bar') + + +    def test_descriptors(self): +        class Foo(object): +            @classmethod +            def f(cls, a, b): +                pass +            @staticmethod +            def g(a, b): +                pass + +        class Bar(Foo): +            pass + +        class Baz(SomeClass, Bar): +            pass + +        for spec in (Foo, Foo(), Bar, Bar(), Baz, Baz()): +            mock = create_autospec(spec) +            mock.f(1, 2) +            mock.f.assert_called_once_with(1, 2) + +            mock.g(3, 4) +            mock.g.assert_called_once_with(3, 4) + + +    def test_recursive(self): +        class A(object): +            def a(self): +                pass +            foo = 'foo bar baz' +            bar = foo + +        A.B = A +        mock = create_autospec(A) + +        mock() +        self.assertFalse(mock.B.called) + +        mock.a() +        mock.B.a() +        self.assertEqual(mock.method_calls, [call.a(), call.B.a()]) + +        self.assertIs(A.foo, A.bar) +        self.assertIsNot(mock.foo, mock.bar) +        mock.foo.lower() +        self.assertRaises(AssertionError, mock.bar.lower.assert_called_with) + + +    def test_spec_inheritance_for_classes(self): +        class Foo(object): +            def a(self): +                pass +            class Bar(object): +                def f(self): +                    pass + +        class_mock = create_autospec(Foo) + +        self.assertIsNot(class_mock, class_mock()) + +        for this_mock in class_mock, class_mock(): +            this_mock.a() +            this_mock.a.assert_called_with() +            self.assertRaises(TypeError, this_mock.a, 'foo') +            self.assertRaises(AttributeError, getattr, this_mock, 'b') + +        instance_mock = create_autospec(Foo()) +        instance_mock.a() +        instance_mock.a.assert_called_with() +        self.assertRaises(TypeError, instance_mock.a, 'foo') +        self.assertRaises(AttributeError, getattr, instance_mock, 'b') + +        # The return value isn't isn't callable +        self.assertRaises(TypeError, instance_mock) + +        instance_mock.Bar.f() +        instance_mock.Bar.f.assert_called_with() +        self.assertRaises(AttributeError, getattr, instance_mock.Bar, 'g') + +        instance_mock.Bar().f() +        instance_mock.Bar().f.assert_called_with() +        self.assertRaises(AttributeError, getattr, instance_mock.Bar(), 'g') + + +    def test_inherit(self): +        class Foo(object): +            a = 3 + +        Foo.Foo = Foo + +        # class +        mock = create_autospec(Foo) +        instance = mock() +        self.assertRaises(AttributeError, getattr, instance, 'b') + +        attr_instance = mock.Foo() +        self.assertRaises(AttributeError, getattr, attr_instance, 'b') + +        # instance +        mock = create_autospec(Foo()) +        self.assertRaises(AttributeError, getattr, mock, 'b') +        self.assertRaises(TypeError, mock) + +        # attribute instance +        call_result = mock.Foo() +        self.assertRaises(AttributeError, getattr, call_result, 'b') + + +    def test_builtins(self): +        # used to fail with infinite recursion +        create_autospec(1) + +        create_autospec(int) +        create_autospec('foo') +        create_autospec(str) +        create_autospec({}) +        create_autospec(dict) +        create_autospec([]) +        create_autospec(list) +        create_autospec(set()) +        create_autospec(set) +        create_autospec(1.0) +        create_autospec(float) +        create_autospec(1j) +        create_autospec(complex) +        create_autospec(False) +        create_autospec(True) + + +    def test_function(self): +        def f(a, b): +            pass + +        mock = create_autospec(f) +        self.assertRaises(TypeError, mock) +        mock(1, 2) +        mock.assert_called_with(1, 2) + +        f.f = f +        mock = create_autospec(f) +        self.assertRaises(TypeError, mock.f) +        mock.f(3, 4) +        mock.f.assert_called_with(3, 4) + + +    def test_skip_attributeerrors(self): +        class Raiser(object): +            def __get__(self, obj, type=None): +                if obj is None: +                    raise AttributeError('Can only be accessed via an instance') + +        class RaiserClass(object): +            raiser = Raiser() + +            @staticmethod +            def existing(a, b): +                return a + b + +        s = create_autospec(RaiserClass) +        self.assertRaises(TypeError, lambda x: s.existing(1, 2, 3)) +        s.existing(1, 2) +        self.assertRaises(AttributeError, lambda: s.nonexisting) + +        # check we can fetch the raiser attribute and it has no spec +        obj = s.raiser +        obj.foo, obj.bar + + +    def test_signature_class(self): +        class Foo(object): +            def __init__(self, a, b=3): +                pass + +        mock = create_autospec(Foo) + +        self.assertRaises(TypeError, mock) +        mock(1) +        mock.assert_called_once_with(1) + +        mock(4, 5) +        mock.assert_called_with(4, 5) + + +    def test_class_with_no_init(self): +        # this used to raise an exception +        # due to trying to get a signature from object.__init__ +        class Foo(object): +            pass +        create_autospec(Foo) + + +    def test_signature_callable(self): +        class Callable(object): +            def __init__(self): +                pass +            def __call__(self, a): +                pass + +        mock = create_autospec(Callable) +        mock() +        mock.assert_called_once_with() +        self.assertRaises(TypeError, mock, 'a') + +        instance = mock() +        self.assertRaises(TypeError, instance) +        instance(a='a') +        instance.assert_called_once_with(a='a') +        instance('a') +        instance.assert_called_with('a') + +        mock = create_autospec(Callable()) +        mock(a='a') +        mock.assert_called_once_with(a='a') +        self.assertRaises(TypeError, mock) +        mock('a') +        mock.assert_called_with('a') + + +    def test_signature_noncallable(self): +        class NonCallable(object): +            def __init__(self): +                pass + +        mock = create_autospec(NonCallable) +        instance = mock() +        mock.assert_called_once_with() +        self.assertRaises(TypeError, mock, 'a') +        self.assertRaises(TypeError, instance) +        self.assertRaises(TypeError, instance, 'a') + +        mock = create_autospec(NonCallable()) +        self.assertRaises(TypeError, mock) +        self.assertRaises(TypeError, mock, 'a') + + +    def test_create_autospec_none(self): +        class Foo(object): +            bar = None + +        mock = create_autospec(Foo) +        none = mock.bar +        self.assertNotIsInstance(none, type(None)) + +        none.foo() +        none.foo.assert_called_once_with() + + +    def test_autospec_functions_with_self_in_odd_place(self): +        class Foo(object): +            def f(a, self): +                pass + +        a = create_autospec(Foo) +        a.f(self=10) +        a.f.assert_called_with(self=10) + + +    def test_autospec_property(self): +        class Foo(object): +            @property +            def foo(self): +                return 3 + +        foo = create_autospec(Foo) +        mock_property = foo.foo + +        # no spec on properties +        self.assertTrue(isinstance(mock_property, MagicMock)) +        mock_property(1, 2, 3) +        mock_property.abc(4, 5, 6) +        mock_property.assert_called_once_with(1, 2, 3) +        mock_property.abc.assert_called_once_with(4, 5, 6) + + +    def test_autospec_slots(self): +        class Foo(object): +            __slots__ = ['a'] + +        foo = create_autospec(Foo) +        mock_slot = foo.a + +        # no spec on slots +        mock_slot(1, 2, 3) +        mock_slot.abc(4, 5, 6) +        mock_slot.assert_called_once_with(1, 2, 3) +        mock_slot.abc.assert_called_once_with(4, 5, 6) + + +class TestCallList(unittest.TestCase): + +    def test_args_list_contains_call_list(self): +        mock = Mock() +        self.assertIsInstance(mock.call_args_list, _CallList) + +        mock(1, 2) +        mock(a=3) +        mock(3, 4) +        mock(b=6) + +        for kall in call(1, 2), call(a=3), call(3, 4), call(b=6): +            self.assertTrue(kall in mock.call_args_list) + +        calls = [call(a=3), call(3, 4)] +        self.assertTrue(calls in mock.call_args_list) +        calls = [call(1, 2), call(a=3)] +        self.assertTrue(calls in mock.call_args_list) +        calls = [call(3, 4), call(b=6)] +        self.assertTrue(calls in mock.call_args_list) +        calls = [call(3, 4)] +        self.assertTrue(calls in mock.call_args_list) + +        self.assertFalse(call('fish') in mock.call_args_list) +        self.assertFalse([call('fish')] in mock.call_args_list) + + +    def test_call_list_str(self): +        mock = Mock() +        mock(1, 2) +        mock.foo(a=3) +        mock.foo.bar().baz('fish', cat='dog') + +        expected = ( +            "[call(1, 2),\n" +            " call.foo(a=3),\n" +            " call.foo.bar(),\n" +            " call.foo.bar().baz('fish', cat='dog')]" +        ) +        self.assertEqual(str(mock.mock_calls), expected) + + +    def test_propertymock(self): +        p = patch('%s.SomeClass.one' % __name__, new_callable=PropertyMock) +        mock = p.start() +        try: +            SomeClass.one +            mock.assert_called_once_with() + +            s = SomeClass() +            s.one +            mock.assert_called_with() +            self.assertEqual(mock.mock_calls, [call(), call()]) + +            s.one = 3 +            self.assertEqual(mock.mock_calls, [call(), call(), call(3)]) +        finally: +            p.stop() + + +    def test_propertymock_returnvalue(self): +        m = MagicMock() +        p = PropertyMock() +        type(m).foo = p + +        returned = m.foo +        p.assert_called_once_with() +        self.assertIsInstance(returned, MagicMock) +        self.assertNotIsInstance(returned, PropertyMock) + + +if __name__ == '__main__': +    unittest.main() diff --git a/Lib/unittest/test/testmock/testmagicmethods.py b/Lib/unittest/test/testmock/testmagicmethods.py new file mode 100644 index 0000000..2bcf088 --- /dev/null +++ b/Lib/unittest/test/testmock/testmagicmethods.py @@ -0,0 +1,403 @@ +import unittest +import inspect +import sys +from unittest.mock import Mock, MagicMock, _magics + + + +class TestMockingMagicMethods(unittest.TestCase): + +    def test_deleting_magic_methods(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 test_magicmock_del(self): +        mock = MagicMock() +        # before using getitem +        del mock.__getitem__ +        self.assertRaises(TypeError, lambda: mock['foo']) + +        mock = MagicMock() +        # this time use it first +        mock['foo'] +        del mock.__getitem__ +        self.assertRaises(TypeError, lambda: mock['foo']) + + +    def test_magic_method_wrapping(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')) +        self.assertEqual(mock.__getitem__('foo'), (mock, 'fish')) + +        mock.__getitem__ = mock +        self.assertTrue(mock.__getitem__ is mock) + + +    def test_magic_methods_isolated_between_mocks(self): +        mock1 = Mock() +        mock2 = Mock() + +        mock1.__iter__ = Mock(return_value=iter([])) +        self.assertEqual(list(mock1), []) +        self.assertRaises(TypeError, lambda: list(mock2)) + + +    def test_repr(self): +        mock = Mock() +        self.assertEqual(repr(mock), "<Mock id='%s'>" % id(mock)) +        mock.__repr__ = lambda s: 'foo' +        self.assertEqual(repr(mock), 'foo') + + +    def test_str(self): +        mock = Mock() +        self.assertEqual(str(mock), object.__str__(mock)) +        mock.__str__ = lambda s: 'foo' +        self.assertEqual(str(mock), 'foo') + + +    def test_dict_methods(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 test_numeric(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 test_hash(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 test_nonzero(self): +        m = Mock() +        self.assertTrue(bool(m)) + +        m.__bool__ = lambda s: False +        self.assertFalse(bool(m)) + + +    def test_comparison(self): +        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) + +        self.assertRaises(TypeError, lambda: MagicMock() < object()) +        self.assertRaises(TypeError, lambda: object() < MagicMock()) +        self.assertRaises(TypeError, lambda: MagicMock() < MagicMock()) +        self.assertRaises(TypeError, lambda: MagicMock() > object()) +        self.assertRaises(TypeError, lambda: object() > MagicMock()) +        self.assertRaises(TypeError, lambda: MagicMock() > MagicMock()) +        self.assertRaises(TypeError, lambda: MagicMock() <= object()) +        self.assertRaises(TypeError, lambda: object() <= MagicMock()) +        self.assertRaises(TypeError, lambda: MagicMock() <= MagicMock()) +        self.assertRaises(TypeError, lambda: MagicMock() >= object()) +        self.assertRaises(TypeError, lambda: object() >= MagicMock()) +        self.assertRaises(TypeError, lambda: MagicMock() >= MagicMock()) + + +    def test_equality(self): +        for mock in Mock(), MagicMock(): +            self.assertEqual(mock == mock, True) +            self.assertIsInstance(mock == mock, bool) +            self.assertEqual(mock != mock, False) +            self.assertIsInstance(mock != mock, bool) +            self.assertEqual(mock == object(), False) +            self.assertEqual(mock != object(), True) + +            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) + +        mock = MagicMock() +        mock.__eq__.return_value = True +        self.assertIsInstance(mock == 3, bool) +        self.assertEqual(mock == 3, True) + +        mock.__ne__.return_value = False +        self.assertIsInstance(mock != 3, bool) +        self.assertEqual(mock != 3, False) + + +    def test_len_contains_iter(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 test_magicmock(self): +        mock = MagicMock() + +        mock.__iter__.return_value = iter([1, 2, 3]) +        self.assertEqual(list(mock), [1, 2, 3]) + +        getattr(mock, '__bool__').return_value = False +        self.assertFalse(hasattr(mock, '__nonzero__')) +        self.assertFalse(bool(mock)) + +        for entry in _magics: +            self.assertTrue(hasattr(mock, entry)) +        self.assertFalse(hasattr(mock, '__imaginery__')) + + +    def test_magic_mock_equality(self): +        mock = MagicMock() +        self.assertIsInstance(mock == object(), bool) +        self.assertIsInstance(mock != object(), bool) + +        self.assertEqual(mock == object(), False) +        self.assertEqual(mock != object(), True) +        self.assertEqual(mock == mock, True) +        self.assertEqual(mock != mock, False) + + +    def test_magicmock_defaults(self): +        mock = MagicMock() +        self.assertEqual(int(mock), 1) +        self.assertEqual(complex(mock), 1j) +        self.assertEqual(float(mock), 1.0) +        self.assertNotIn(object(), mock) +        self.assertEqual(len(mock), 0) +        self.assertEqual(list(mock), []) +        self.assertEqual(hash(mock), object.__hash__(mock)) +        self.assertEqual(str(mock), object.__str__(mock)) +        self.assertTrue(bool(mock)) + +        # in Python 3 oct and hex use __index__ +        # so these tests are for __index__ in py3k +        self.assertEqual(oct(mock), '0o1') +        self.assertEqual(hex(mock), '0x1') +        # how to test __sizeof__ ? + + +    def test_magic_methods_and_spec(self): +        class Iterable(object): +            def __iter__(self): +                pass + +        mock = Mock(spec=Iterable) +        self.assertRaises(AttributeError, lambda: mock.__iter__) + +        mock.__iter__ = Mock(return_value=iter([])) +        self.assertEqual(list(mock), []) + +        class NonIterable(object): +            pass +        mock = Mock(spec=NonIterable) +        self.assertRaises(AttributeError, lambda: mock.__iter__) + +        def set_int(): +            mock.__int__ = Mock(return_value=iter([])) +        self.assertRaises(AttributeError, set_int) + +        mock = MagicMock(spec=Iterable) +        self.assertEqual(list(mock), []) +        self.assertRaises(AttributeError, set_int) + + +    def test_magic_methods_and_spec_set(self): +        class Iterable(object): +            def __iter__(self): +                pass + +        mock = Mock(spec_set=Iterable) +        self.assertRaises(AttributeError, lambda: mock.__iter__) + +        mock.__iter__ = Mock(return_value=iter([])) +        self.assertEqual(list(mock), []) + +        class NonIterable(object): +            pass +        mock = Mock(spec_set=NonIterable) +        self.assertRaises(AttributeError, lambda: mock.__iter__) + +        def set_int(): +            mock.__int__ = Mock(return_value=iter([])) +        self.assertRaises(AttributeError, set_int) + +        mock = MagicMock(spec_set=Iterable) +        self.assertEqual(list(mock), []) +        self.assertRaises(AttributeError, set_int) + + +    def test_setting_unsupported_magic_method(self): +        mock = MagicMock() +        def set_setattr(): +            mock.__setattr__ = lambda self, name: None +        self.assertRaisesRegex(AttributeError, +            "Attempting to set unsupported magic method '__setattr__'.", +            set_setattr +        ) + + +    def test_attributes_and_return_value(self): +        mock = MagicMock() +        attr = mock.foo +        def _get_type(obj): +            # the type of every mock (or magicmock) is a custom subclass +            # so the real type is the second in the mro +            return type(obj).__mro__[1] +        self.assertEqual(_get_type(attr), MagicMock) + +        returned = mock() +        self.assertEqual(_get_type(returned), MagicMock) + + +    def test_magic_methods_are_magic_mocks(self): +        mock = MagicMock() +        self.assertIsInstance(mock.__getitem__, MagicMock) + +        mock[1][2].__getitem__.return_value = 3 +        self.assertEqual(mock[1][2][3], 3) + + +    def test_magic_method_reset_mock(self): +        mock = MagicMock() +        str(mock) +        self.assertTrue(mock.__str__.called) +        mock.reset_mock() +        self.assertFalse(mock.__str__.called) + + +    def test_dir(self): +        # overriding the default implementation +        for mock in Mock(), MagicMock(): +            def _dir(self): +                return ['foo'] +            mock.__dir__ = _dir +            self.assertEqual(dir(mock), ['foo']) + + +    @unittest.skipIf('PyPy' in sys.version, "This fails differently on pypy") +    def test_bound_methods(self): +        m = Mock() + +        # XXXX should this be an expected failure instead? + +        # this seems like it should work, but is hard to do without introducing +        # other api inconsistencies. Failure message could be better though. +        m.__iter__ = [3].__iter__ +        self.assertRaises(TypeError, iter, m) + + +    def test_magic_method_type(self): +        class Foo(MagicMock): +            pass + +        foo = Foo() +        self.assertIsInstance(foo.__int__, Foo) + + +    def test_descriptor_from_class(self): +        m = MagicMock() +        type(m).__str__.return_value = 'foo' +        self.assertEqual(str(m), 'foo') + + +    def test_iterable_as_iter_return_value(self): +        m = MagicMock() +        m.__iter__.return_value = [1, 2, 3] +        self.assertEqual(list(m), [1, 2, 3]) +        self.assertEqual(list(m), [1, 2, 3]) + +        m.__iter__.return_value = iter([4, 5, 6]) +        self.assertEqual(list(m), [4, 5, 6]) +        self.assertEqual(list(m), []) + + +if __name__ == '__main__': +    unittest.main() diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py new file mode 100644 index 0000000..2c6f128 --- /dev/null +++ b/Lib/unittest/test/testmock/testmock.py @@ -0,0 +1,1275 @@ +import copy +import sys + +import unittest +from unittest.test.testmock.support import is_instance +from unittest import mock +from unittest.mock import ( +    call, DEFAULT, patch, sentinel, +    MagicMock, Mock, NonCallableMock, +    NonCallableMagicMock, _CallList, +    create_autospec +) + + +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 MockTest(unittest.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 unittest.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_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) + + +    @unittest.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.assertRaisesRegex( +                    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.assertRaisesRegex( +                AttributeError, +                "Mock object has no attribute 'z'", +                getattr, mock, 'z' +            ) +            self.assertRaisesRegex( +                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.assertRaisesRegex(AssertionError, 'Not called', +                                mock.assert_called_with) + + +    def test_assert_called_once_with_message(self): +        mock = Mock(name='geoffrey') +        self.assertRaisesRegex(AssertionError, +                     r"Expected 'geoffrey' to be called once\.", +                     mock.assert_called_once_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()) + + +    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') + + +    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)) + + +    def test_dir_from_spec(self): +        mock = Mock(spec=unittest.TestCase) +        testcase_attrs = set(dir(unittest.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) + + +    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_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_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_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) +            mock.foo + + + +if __name__ == '__main__': +    unittest.main() diff --git a/Lib/unittest/test/testmock/testpatch.py b/Lib/unittest/test/testmock/testpatch.py new file mode 100644 index 0000000..c1091b4 --- /dev/null +++ b/Lib/unittest/test/testmock/testpatch.py @@ -0,0 +1,1785 @@ +# 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() + + +    def test_patch_stopall(self): +        unlink = os.unlink +        chdir = os.chdir +        path = os.path +        patch('os.unlink', something).start() +        patch('os.chdir', something_else).start() + +        @patch('os.path') +        def patched(mock_path): +            patch.stopall() +            self.assertIs(os.path, mock_path) +            self.assertIs(os.unlink, unlink) +            self.assertIs(os.chdir, chdir) + +        patched() +        self.assertIs(os.path, path) + + + +if __name__ == '__main__': +    unittest.main() diff --git a/Lib/unittest/test/testmock/testsentinel.py b/Lib/unittest/test/testmock/testsentinel.py new file mode 100644 index 0000000..bfda68e --- /dev/null +++ b/Lib/unittest/test/testmock/testsentinel.py @@ -0,0 +1,28 @@ +import unittest +from unittest.mock import sentinel, DEFAULT + + +class SentinelTest(unittest.TestCase): + +    def testSentinels(self): +        self.assertEqual(sentinel.whatever, sentinel.whatever, +                         'sentinel not stored') +        self.assertNotEqual(sentinel.whatever, sentinel.whateverelse, +                            'sentinel should be unique') + + +    def testSentinelName(self): +        self.assertEqual(str(sentinel.whatever), 'sentinel.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__': +    unittest.main() diff --git a/Lib/unittest/test/testmock/testwith.py b/Lib/unittest/test/testmock/testwith.py new file mode 100644 index 0000000..0a0cfad --- /dev/null +++ b/Lib/unittest/test/testmock/testwith.py @@ -0,0 +1,176 @@ +import unittest +from warnings import catch_warnings + +from unittest.test.testmock.support import is_instance +from unittest.mock import MagicMock, Mock, patch, sentinel, mock_open, call + + + +something  = sentinel.Something +something_else  = sentinel.SomethingElse + + + +class WithTest(unittest.TestCase): + +    def test_with_statement(self): +        with patch('%s.something' % __name__, sentinel.Something2): +            self.assertEqual(something, sentinel.Something2, "unpatched") +        self.assertEqual(something, sentinel.Something) + + +    def test_with_statement_exception(self): +        try: +            with patch('%s.something' % __name__, sentinel.Something2): +                self.assertEqual(something, sentinel.Something2, "unpatched") +                raise Exception('pow') +        except Exception: +            pass +        else: +            self.fail("patch swallowed exception") +        self.assertEqual(something, sentinel.Something) + + +    def test_with_statement_as(self): +        with patch('%s.something' % __name__) as mock_something: +            self.assertEqual(something, mock_something, "unpatched") +            self.assertTrue(is_instance(mock_something, MagicMock), +                            "patching wrong type") +        self.assertEqual(something, sentinel.Something) + + +    def test_patch_object_with_statement(self): +        class Foo(object): +            something = 'foo' +        original = Foo.something +        with patch.object(Foo, 'something'): +            self.assertNotEqual(Foo.something, original, "unpatched") +        self.assertEqual(Foo.something, original) + + +    def test_with_statement_nested(self): +        with catch_warnings(record=True): +            with patch('%s.something' % __name__) as mock_something, patch('%s.something_else' % __name__) as mock_something_else: +                self.assertEqual(something, mock_something, "unpatched") +                self.assertEqual(something_else, mock_something_else, +                                 "unpatched") + +        self.assertEqual(something, sentinel.Something) +        self.assertEqual(something_else, sentinel.SomethingElse) + + +    def test_with_statement_specified(self): +        with patch('%s.something' % __name__, sentinel.Patched) as mock_something: +            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 test_context_manager_with_magic_mock(self): +        mock = MagicMock() + +        with self.assertRaises(TypeError): +            with mock: +                'foo' + 3 +        mock.__enter__.assert_called_with() +        self.assertTrue(mock.__exit__.called) + + +    def test_with_statement_same_attribute(self): +        with patch('%s.something' % __name__, sentinel.Patched) as mock_something: +            self.assertEqual(something, mock_something, "unpatched") + +            with patch('%s.something' % __name__) as mock_again: +                self.assertEqual(something, mock_again, "unpatched") + +            self.assertEqual(something, mock_something, +                             "restored with wrong instance") + +        self.assertEqual(something, sentinel.Something, "not restored") + + +    def test_with_statement_imbricated(self): +        with patch('%s.something' % __name__) as mock_something: +            self.assertEqual(something, mock_something, "unpatched") + +            with patch('%s.something_else' % __name__) as mock_something_else: +                self.assertEqual(something_else, mock_something_else, +                                 "unpatched") + +        self.assertEqual(something, sentinel.Something) +        self.assertEqual(something_else, sentinel.SomethingElse) + + +    def test_dict_context_manager(self): +        foo = {} +        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, {}) + + + +class TestMockOpen(unittest.TestCase): + +    def test_mock_open(self): +        mock = mock_open() +        with patch('%s.open' % __name__, mock, create=True) as patched: +            self.assertIs(patched, mock) +            open('foo') + +        mock.assert_called_once_with('foo') + + +    def test_mock_open_context_manager(self): +        mock = mock_open() +        handle = mock.return_value +        with patch('%s.open' % __name__, mock, create=True): +            with open('foo') as f: +                f.read() + +        expected_calls = [call('foo'), call().__enter__(), call().read(), +                          call().__exit__(None, None, None)] +        self.assertEqual(mock.mock_calls, expected_calls) +        self.assertIs(f, handle) + + +    def test_explicit_mock(self): +        mock = MagicMock() +        mock_open(mock) + +        with patch('%s.open' % __name__, mock, create=True) as patched: +            self.assertIs(patched, mock) +            open('foo') + +        mock.assert_called_once_with('foo') + + +    def test_read_data(self): +        mock = mock_open(read_data='foo') +        with patch('%s.open' % __name__, mock, create=True): +            h = open('bar') +            result = h.read() + +        self.assertEqual(result, 'foo') + + +if __name__ == '__main__': +    unittest.main()  | 
