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