|
10 | 10 | from mock.mock import _Call, _CallList, _callable
|
11 | 11 | from mock import IS_PYPY
|
12 | 12 |
|
| 13 | +try: |
| 14 | + from dataclasses import dataclass, field, InitVar |
| 15 | +except ImportError: |
| 16 | + pass |
| 17 | + |
13 | 18 | from datetime import datetime
|
14 | 19 | from functools import partial
|
| 20 | +from typing import ClassVar |
15 | 21 |
|
16 | 22 | import pytest
|
| 23 | +import sys |
17 | 24 |
|
18 | 25 |
|
19 | 26 | class SomeClass(object):
|
@@ -1043,6 +1050,80 @@ def f(a): pass
|
1043 | 1050 | self.assertEqual(mock.mock_calls, [])
|
1044 | 1051 | self.assertEqual(rv.mock_calls, [])
|
1045 | 1052 |
|
| 1053 | + @pytest.mark.skipif(sys.version_info < (3, 7), reason="requires python 3.7 or higher") |
| 1054 | + def test_dataclass_post_init(self): |
| 1055 | + @dataclass |
| 1056 | + class WithPostInit: |
| 1057 | + a: int = field(init=False) |
| 1058 | + b: int = field(init=False) |
| 1059 | + def __post_init__(self): |
| 1060 | + self.a = 1 |
| 1061 | + self.b = 2 |
| 1062 | + |
| 1063 | + for mock in [ |
| 1064 | + create_autospec(WithPostInit, instance=True), |
| 1065 | + create_autospec(WithPostInit()), |
| 1066 | + ]: |
| 1067 | + with self.subTest(mock=mock): |
| 1068 | + self.assertIsInstance(mock.a, int) |
| 1069 | + self.assertIsInstance(mock.b, int) |
| 1070 | + |
| 1071 | + # Classes do not have these fields: |
| 1072 | + mock = create_autospec(WithPostInit) |
| 1073 | + msg = "Mock object has no attribute" |
| 1074 | + with self.assertRaisesRegex(AttributeError, msg): |
| 1075 | + mock.a |
| 1076 | + with self.assertRaisesRegex(AttributeError, msg): |
| 1077 | + mock.b |
| 1078 | + |
| 1079 | + @pytest.mark.skipif(sys.version_info < (3, 7), reason="requires python 3.7 or higher") |
| 1080 | + def test_dataclass_default(self): |
| 1081 | + @dataclass |
| 1082 | + class WithDefault: |
| 1083 | + a: int |
| 1084 | + b: int = 0 |
| 1085 | + |
| 1086 | + for mock in [ |
| 1087 | + create_autospec(WithDefault, instance=True), |
| 1088 | + create_autospec(WithDefault(1)), |
| 1089 | + ]: |
| 1090 | + with self.subTest(mock=mock): |
| 1091 | + self.assertIsInstance(mock.a, int) |
| 1092 | + self.assertIsInstance(mock.b, int) |
| 1093 | + |
| 1094 | + @pytest.mark.skipif(sys.version_info < (3, 7), reason="requires python 3.7 or higher") |
| 1095 | + def test_dataclass_with_method(self): |
| 1096 | + @dataclass |
| 1097 | + class WithMethod: |
| 1098 | + a: int |
| 1099 | + def b(self) -> int: |
| 1100 | + return 1 |
| 1101 | + |
| 1102 | + for mock in [ |
| 1103 | + create_autospec(WithMethod, instance=True), |
| 1104 | + create_autospec(WithMethod(1)), |
| 1105 | + ]: |
| 1106 | + with self.subTest(mock=mock): |
| 1107 | + self.assertIsInstance(mock.a, int) |
| 1108 | + mock.b.assert_not_called() |
| 1109 | + |
| 1110 | + @pytest.mark.skipif(sys.version_info < (3, 7), reason="requires python 3.7 or higher") |
| 1111 | + def test_dataclass_with_non_fields(self): |
| 1112 | + @dataclass |
| 1113 | + class WithNonFields: |
| 1114 | + a: ClassVar[int] |
| 1115 | + b: InitVar[int] |
| 1116 | + |
| 1117 | + msg = "Mock object has no attribute" |
| 1118 | + for mock in [ |
| 1119 | + create_autospec(WithNonFields, instance=True), |
| 1120 | + create_autospec(WithNonFields(1)), |
| 1121 | + ]: |
| 1122 | + with self.subTest(mock=mock): |
| 1123 | + with self.assertRaisesRegex(AttributeError, msg): |
| 1124 | + mock.a |
| 1125 | + with self.assertRaisesRegex(AttributeError, msg): |
| 1126 | + mock.b |
1046 | 1127 |
|
1047 | 1128 | class TestCallList(unittest.TestCase):
|
1048 | 1129 |
|
|
0 commit comments