1import unittest 2from unittest import mock 3 4 5class SampleObject: 6 7 def method_sample1(self): pass 8 9 def method_sample2(self): pass 10 11 12class TestSealable(unittest.TestCase): 13 14 def test_attributes_return_more_mocks_by_default(self): 15 m = mock.Mock() 16 17 self.assertIsInstance(m.test, mock.Mock) 18 self.assertIsInstance(m.test(), mock.Mock) 19 self.assertIsInstance(m.test().test2(), mock.Mock) 20 21 def test_new_attributes_cannot_be_accessed_on_seal(self): 22 m = mock.Mock() 23 24 mock.seal(m) 25 with self.assertRaises(AttributeError): 26 m.test 27 with self.assertRaises(AttributeError): 28 m() 29 30 def test_new_attributes_cannot_be_set_on_seal(self): 31 m = mock.Mock() 32 33 mock.seal(m) 34 with self.assertRaises(AttributeError): 35 m.test = 1 36 37 def test_existing_attributes_can_be_set_on_seal(self): 38 m = mock.Mock() 39 m.test.test2 = 1 40 41 mock.seal(m) 42 m.test.test2 = 2 43 self.assertEqual(m.test.test2, 2) 44 45 def test_new_attributes_cannot_be_set_on_child_of_seal(self): 46 m = mock.Mock() 47 m.test.test2 = 1 48 49 mock.seal(m) 50 with self.assertRaises(AttributeError): 51 m.test.test3 = 1 52 53 def test_existing_attributes_allowed_after_seal(self): 54 m = mock.Mock() 55 56 m.test.return_value = 3 57 58 mock.seal(m) 59 self.assertEqual(m.test(), 3) 60 61 def test_initialized_attributes_allowed_after_seal(self): 62 m = mock.Mock(test_value=1) 63 64 mock.seal(m) 65 self.assertEqual(m.test_value, 1) 66 67 def test_call_on_sealed_mock_fails(self): 68 m = mock.Mock() 69 70 mock.seal(m) 71 with self.assertRaises(AttributeError): 72 m() 73 74 def test_call_on_defined_sealed_mock_succeeds(self): 75 m = mock.Mock(return_value=5) 76 77 mock.seal(m) 78 self.assertEqual(m(), 5) 79 80 def test_seals_recurse_on_added_attributes(self): 81 m = mock.Mock() 82 83 m.test1.test2().test3 = 4 84 85 mock.seal(m) 86 self.assertEqual(m.test1.test2().test3, 4) 87 with self.assertRaises(AttributeError): 88 m.test1.test2().test4 89 with self.assertRaises(AttributeError): 90 m.test1.test3 91 92 def test_seals_recurse_on_magic_methods(self): 93 m = mock.MagicMock() 94 95 m.test1.test2["a"].test3 = 4 96 m.test1.test3[2:5].test3 = 4 97 98 mock.seal(m) 99 self.assertEqual(m.test1.test2["a"].test3, 4) 100 self.assertEqual(m.test1.test2[2:5].test3, 4) 101 with self.assertRaises(AttributeError): 102 m.test1.test2["a"].test4 103 with self.assertRaises(AttributeError): 104 m.test1.test3[2:5].test4 105 106 def test_seals_dont_recurse_on_manual_attributes(self): 107 m = mock.Mock(name="root_mock") 108 109 m.test1.test2 = mock.Mock(name="not_sealed") 110 m.test1.test2.test3 = 4 111 112 mock.seal(m) 113 self.assertEqual(m.test1.test2.test3, 4) 114 m.test1.test2.test4 # Does not raise 115 m.test1.test2.test4 = 1 # Does not raise 116 117 def test_integration_with_spec_att_definition(self): 118 """You are not restricted when using mock with spec""" 119 m = mock.Mock(SampleObject) 120 121 m.attr_sample1 = 1 122 m.attr_sample3 = 3 123 124 mock.seal(m) 125 self.assertEqual(m.attr_sample1, 1) 126 self.assertEqual(m.attr_sample3, 3) 127 with self.assertRaises(AttributeError): 128 m.attr_sample2 129 130 def test_integration_with_spec_method_definition(self): 131 """You need to defin the methods, even if they are in the spec""" 132 m = mock.Mock(SampleObject) 133 134 m.method_sample1.return_value = 1 135 136 mock.seal(m) 137 self.assertEqual(m.method_sample1(), 1) 138 with self.assertRaises(AttributeError): 139 m.method_sample2() 140 141 def test_integration_with_spec_method_definition_respects_spec(self): 142 """You cannot define methods out of the spec""" 143 m = mock.Mock(SampleObject) 144 145 with self.assertRaises(AttributeError): 146 m.method_sample3.return_value = 3 147 148 def test_sealed_exception_has_attribute_name(self): 149 m = mock.Mock() 150 151 mock.seal(m) 152 with self.assertRaises(AttributeError) as cm: 153 m.SECRETE_name 154 self.assertIn("SECRETE_name", str(cm.exception)) 155 156 def test_attribute_chain_is_maintained(self): 157 m = mock.Mock(name="mock_name") 158 m.test1.test2.test3.test4 159 160 mock.seal(m) 161 with self.assertRaises(AttributeError) as cm: 162 m.test1.test2.test3.test4.boom 163 self.assertIn("mock_name.test1.test2.test3.test4.boom", str(cm.exception)) 164 165 def test_call_chain_is_maintained(self): 166 m = mock.Mock() 167 m.test1().test2.test3().test4 168 169 mock.seal(m) 170 with self.assertRaises(AttributeError) as cm: 171 m.test1().test2.test3().test4() 172 self.assertIn("mock.test1().test2.test3().test4", str(cm.exception)) 173 174 175if __name__ == "__main__": 176 unittest.main() 177