testsealable.py 5.0 KB

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