bpo-31177: Skip deleted attributes while calling reset_mock (GH-9302)

diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py
index a9c82dc..9547b1a 100644
--- a/Lib/unittest/mock.py
+++ b/Lib/unittest/mock.py
@@ -542,7 +542,7 @@
             self._mock_side_effect = None
 
         for child in self._mock_children.values():
-            if isinstance(child, _SpecState):
+            if isinstance(child, _SpecState) or child is _deleted:
                 continue
             child.reset_mock(visited)
 
diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py
index 8cd284a..ac6eea3 100644
--- a/Lib/unittest/test/testmock/testmock.py
+++ b/Lib/unittest/test/testmock/testmock.py
@@ -1596,6 +1596,16 @@
             self.assertRaises(AttributeError, getattr, mock, 'f')
 
 
+    def test_reset_mock_does_not_raise_on_attr_deletion(self):
+        # bpo-31177: reset_mock should not raise AttributeError when attributes
+        # were deleted in a mock instance
+        mock = Mock()
+        mock.child = True
+        del mock.child
+        mock.reset_mock()
+        self.assertFalse(hasattr(mock, 'child'))
+
+
     def test_class_assignable(self):
         for mock in Mock(), MagicMock():
             self.assertNotIsInstance(mock, int)