1# Copyright (C) 2007-2012 Michael Foord & the mock team
2# E-mail: fuzzyman AT voidspace DOT org DOT uk
3# http://www.voidspace.org.uk/python/mock/
4
5from tests.support import is_instance, unittest2, X, SomeClass
6
7from mock import (
8    Mock, MagicMock, NonCallableMagicMock,
9    NonCallableMock, patch, create_autospec,
10    CallableMixin
11)
12
13
14
15class TestCallable(unittest2.TestCase):
16
17    def assertNotCallable(self, mock):
18        self.assertTrue(is_instance(mock, NonCallableMagicMock))
19        self.assertFalse(is_instance(mock, CallableMixin))
20
21
22    def test_non_callable(self):
23        for mock in NonCallableMagicMock(), NonCallableMock():
24            self.assertRaises(TypeError, mock)
25            self.assertFalse(hasattr(mock, '__call__'))
26            self.assertIn(mock.__class__.__name__, repr(mock))
27
28
29    def test_heirarchy(self):
30        self.assertTrue(issubclass(MagicMock, Mock))
31        self.assertTrue(issubclass(NonCallableMagicMock, NonCallableMock))
32
33
34    def test_attributes(self):
35        one = NonCallableMock()
36        self.assertTrue(issubclass(type(one.one), Mock))
37
38        two = NonCallableMagicMock()
39        self.assertTrue(issubclass(type(two.two), MagicMock))
40
41
42    def test_subclasses(self):
43        class MockSub(Mock):
44            pass
45
46        one = MockSub()
47        self.assertTrue(issubclass(type(one.one), MockSub))
48
49        class MagicSub(MagicMock):
50            pass
51
52        two = MagicSub()
53        self.assertTrue(issubclass(type(two.two), MagicSub))
54
55
56    def test_patch_spec(self):
57        patcher = patch('%s.X' % __name__, spec=True)
58        mock = patcher.start()
59        self.addCleanup(patcher.stop)
60
61        instance = mock()
62        mock.assert_called_once_with()
63
64        self.assertNotCallable(instance)
65        self.assertRaises(TypeError, instance)
66
67
68    def test_patch_spec_set(self):
69        patcher = patch('%s.X' % __name__, spec_set=True)
70        mock = patcher.start()
71        self.addCleanup(patcher.stop)
72
73        instance = mock()
74        mock.assert_called_once_with()
75
76        self.assertNotCallable(instance)
77        self.assertRaises(TypeError, instance)
78
79
80    def test_patch_spec_instance(self):
81        patcher = patch('%s.X' % __name__, spec=X())
82        mock = patcher.start()
83        self.addCleanup(patcher.stop)
84
85        self.assertNotCallable(mock)
86        self.assertRaises(TypeError, mock)
87
88
89    def test_patch_spec_set_instance(self):
90        patcher = patch('%s.X' % __name__, spec_set=X())
91        mock = patcher.start()
92        self.addCleanup(patcher.stop)
93
94        self.assertNotCallable(mock)
95        self.assertRaises(TypeError, mock)
96
97
98    def test_patch_spec_callable_class(self):
99        class CallableX(X):
100            def __call__(self):
101                pass
102
103        class Sub(CallableX):
104            pass
105
106        class Multi(SomeClass, Sub):
107            pass
108
109        class OldStyle:
110            def __call__(self):
111                pass
112
113        class OldStyleSub(OldStyle):
114            pass
115
116        for arg in 'spec', 'spec_set':
117            for Klass in CallableX, Sub, Multi, OldStyle, OldStyleSub:
118                patcher = patch('%s.X' % __name__, **{arg: Klass})
119                mock = patcher.start()
120
121                try:
122                    instance = mock()
123                    mock.assert_called_once_with()
124
125                    self.assertTrue(is_instance(instance, MagicMock))
126                    # inherited spec
127                    self.assertRaises(AttributeError, getattr, instance,
128                                      'foobarbaz')
129
130                    result = instance()
131                    # instance is callable, result has no spec
132                    instance.assert_called_once_with()
133
134                    result(3, 2, 1)
135                    result.assert_called_once_with(3, 2, 1)
136                    result.foo(3, 2, 1)
137                    result.foo.assert_called_once_with(3, 2, 1)
138                finally:
139                    patcher.stop()
140
141
142    def test_create_autopsec(self):
143        mock = create_autospec(X)
144        instance = mock()
145        self.assertRaises(TypeError, instance)
146
147        mock = create_autospec(X())
148        self.assertRaises(TypeError, mock)
149
150
151    def test_create_autospec_instance(self):
152        mock = create_autospec(SomeClass, instance=True)
153
154        self.assertRaises(TypeError, mock)
155        mock.wibble()
156        mock.wibble.assert_called_once_with()
157
158        self.assertRaises(TypeError, mock.wibble, 'some',  'args')
159