test_nested_mock_patch.py
1 from pathlib import Path 2 3 from clint.config import Config 4 from clint.index import SymbolIndex 5 from clint.linter import Position, Range, lint_file 6 from clint.rules.nested_mock_patch import NestedMockPatch 7 8 9 def test_nested_mock_patch_unittest_mock(index: SymbolIndex) -> None: 10 code = """ 11 import unittest.mock 12 13 def test_foo(): 14 with unittest.mock.patch("foo.bar"): 15 with unittest.mock.patch("foo.baz"): 16 ... 17 """ 18 config = Config(select={NestedMockPatch.name}) 19 violations = lint_file(Path("test_nested_mock_patch.py"), code, config, index) 20 assert len(violations) == 1 21 assert all(isinstance(v.rule, NestedMockPatch) for v in violations) 22 assert violations[0].range == Range(Position(4, 4)) 23 24 25 def test_nested_mock_patch_from_unittest_import_mock(index: SymbolIndex) -> None: 26 code = """ 27 from unittest import mock 28 29 def test_foo(): 30 with mock.patch("foo.bar"): 31 with mock.patch("foo.baz"): 32 ... 33 """ 34 config = Config(select={NestedMockPatch.name}) 35 violations = lint_file(Path("test_nested_mock_patch.py"), code, config, index) 36 assert len(violations) == 1 37 assert all(isinstance(v.rule, NestedMockPatch) for v in violations) 38 assert violations[0].range == Range(Position(4, 4)) 39 40 41 def test_nested_mock_patch_object(index: SymbolIndex) -> None: 42 code = """ 43 from unittest import mock 44 45 def test_foo(): 46 with mock.patch.object(SomeClass, "method"): 47 with mock.patch.object(AnotherClass, "method"): 48 ... 49 """ 50 config = Config(select={NestedMockPatch.name}) 51 violations = lint_file(Path("test_nested_mock_patch.py"), code, config, index) 52 assert len(violations) == 1 53 assert all(isinstance(v.rule, NestedMockPatch) for v in violations) 54 assert violations[0].range == Range(Position(4, 4)) 55 56 57 def test_nested_mock_patch_dict(index: SymbolIndex) -> None: 58 code = """ 59 from unittest import mock 60 61 def test_foo(): 62 with mock.patch.dict("os.environ", {"FOO": "bar"}): 63 with mock.patch.dict("os.environ", {"BAZ": "qux"}): 64 ... 65 """ 66 config = Config(select={NestedMockPatch.name}) 67 violations = lint_file(Path("test_nested_mock_patch.py"), code, config, index) 68 assert len(violations) == 1 69 assert all(isinstance(v.rule, NestedMockPatch) for v in violations) 70 assert violations[0].range == Range(Position(4, 4)) 71 72 73 def test_nested_mock_patch_mixed(index: SymbolIndex) -> None: 74 code = """ 75 from unittest import mock 76 77 def test_foo(): 78 with mock.patch("foo.bar"): 79 with mock.patch.object(SomeClass, "method"): 80 ... 81 """ 82 config = Config(select={NestedMockPatch.name}) 83 violations = lint_file(Path("test_nested_mock_patch.py"), code, config, index) 84 assert len(violations) == 1 85 assert all(isinstance(v.rule, NestedMockPatch) for v in violations) 86 assert violations[0].range == Range(Position(4, 4)) 87 88 89 def test_multiple_context_managers_is_ok(index: SymbolIndex) -> None: 90 code = """ 91 from unittest import mock 92 93 def test_foo(): 94 with mock.patch("foo.bar"), mock.patch("foo.baz"): 95 ... 96 """ 97 config = Config(select={NestedMockPatch.name}) 98 violations = lint_file(Path("test_nested_mock_patch.py"), code, config, index) 99 assert len(violations) == 0 100 101 102 def test_multiple_context_managers_with_object_is_ok(index: SymbolIndex) -> None: 103 code = """ 104 from unittest import mock 105 106 def test_foo(): 107 with mock.patch("foo.bar"), mock.patch.object(SomeClass, "method"): 108 ... 109 """ 110 config = Config(select={NestedMockPatch.name}) 111 violations = lint_file(Path("test_nested_mock_patch.py"), code, config, index) 112 assert len(violations) == 0 113 114 115 def test_nested_with_but_not_mock_patch_is_ok(index: SymbolIndex) -> None: 116 code = """ 117 def test_foo(): 118 with open("file.txt"): 119 with open("file2.txt"): 120 ... 121 """ 122 config = Config(select={NestedMockPatch.name}) 123 violations = lint_file(Path("test_nested_mock_patch.py"), code, config, index) 124 assert len(violations) == 0 125 126 127 def test_nested_with_only_one_mock_patch_is_ok(index: SymbolIndex) -> None: 128 code = """ 129 from unittest import mock 130 131 def test_foo(): 132 with mock.patch("foo.bar"): 133 with open("file.txt"): 134 ... 135 """ 136 config = Config(select={NestedMockPatch.name}) 137 violations = lint_file(Path("test_nested_mock_patch.py"), code, config, index) 138 assert len(violations) == 0 139 140 141 def test_non_nested_mock_patches_are_ok(index: SymbolIndex) -> None: 142 code = """ 143 from unittest import mock 144 145 def test_foo(): 146 with mock.patch("foo.bar"): 147 pass 148 with mock.patch("foo.baz"): 149 pass 150 """ 151 config = Config(select={NestedMockPatch.name}) 152 violations = lint_file(Path("test_nested_mock_patch.py"), code, config, index) 153 assert len(violations) == 0 154 155 156 def test_non_test_file_not_checked(index: SymbolIndex) -> None: 157 code = """ 158 from unittest import mock 159 160 def foo(): 161 with mock.patch("foo.bar"): 162 with mock.patch("foo.baz"): 163 ... 164 """ 165 config = Config(select={NestedMockPatch.name}) 166 violations = lint_file(Path("nested_mock_patch.py"), code, config, index) 167 assert len(violations) == 0 168 169 170 def test_nested_with_code_after_is_ok(index: SymbolIndex) -> None: 171 code = """ 172 from unittest import mock 173 174 def test_foo(): 175 with mock.patch("foo.bar"): 176 with mock.patch("foo.baz"): 177 ... 178 179 assert True 180 """ 181 config = Config(select={NestedMockPatch.name}) 182 violations = lint_file(Path("test_nested_mock_patch.py"), code, config, index) 183 assert len(violations) == 0 184 185 186 def test_deeply_nested_mock_patch(index: SymbolIndex) -> None: 187 code = """ 188 from unittest import mock 189 190 def test_foo(): 191 with mock.patch("foo.bar"): 192 with mock.patch("foo.baz"): 193 with mock.patch("foo.qux"): 194 ... 195 """ 196 config = Config(select={NestedMockPatch.name}) 197 violations = lint_file(Path("test_nested_mock_patch.py"), code, config, index) 198 # Should detect both levels of nesting 199 assert len(violations) == 2 200 assert all(isinstance(v.rule, NestedMockPatch) for v in violations) 201 assert violations[0].range == Range(Position(4, 4)) 202 assert violations[1].range == Range(Position(5, 8))