From a5b7b8885626398b9a883b74ba651e8128ad7585 Mon Sep 17 00:00:00 2001
From: Mike McLean <mikem@redhat.com>
Date: Mar 29 2024 22:58:46 +0000
Subject: [PATCH 1/3] rework DBQueryTestCase mocking


Mocking kojihub.kojihub.QueryProcessor doesn't affect other import
paths, e.g. in other kojihub modules

---

diff --git a/tests/test_hub/utils.py b/tests/test_hub/utils.py
index 4ac0b6c..f2e05c3 100644
--- a/tests/test_hub/utils.py
+++ b/tests/test_hub/utils.py
@@ -2,8 +2,27 @@ import mock
 import unittest
 
 import kojihub
+import kojihub.db
 
-QP = kojihub.QueryProcessor
+
+def get_qp_init(testcase):
+    orig_qp_init = kojihub.db.QueryProcessor.__init__
+
+    def my_qp_init(_query, *a, **kw):
+        _query.execute = mock.MagicMock()
+        _query.execute.return_value = testcase.qp_execute_return_value
+        _query.execute.side_effect = testcase.qp_execute_side_effect
+        _query.executeOne = mock.MagicMock()
+        _query.executeOne.return_value = testcase.qp_execute_one_return_value
+        _query.executeOne.side_effect = testcase.qp_execute_one_side_effect
+        _query.singleValue = mock.MagicMock()
+        _query.singleValue.return_value = testcase.qp_single_value_return_value
+        _query.iterate = mock.MagicMock()
+        _query.iterate.return_value = testcase.qp_iterate_return_value
+        testcase.queries.append(_query)
+        return orig_qp_init(_query, *a, **kw)
+
+    return my_qp_init
 
 
 class DBQueryTestCase(unittest.TestCase):
@@ -16,8 +35,11 @@ class DBQueryTestCase(unittest.TestCase):
         self.qp_execute_one_side_effect = None
         self.qp_single_value_return_value = None
         self.qp_iterate_return_value = None
-        self.QueryProcessor = mock.patch('kojihub.kojihub.QueryProcessor',
-                                         side_effect=self.get_query).start()
+
+        # patch init to catch queries regardless of how QP is imported
+        new_init = get_qp_init(self)
+        self.qp_init = mock.patch('kojihub.db.QueryProcessor.__init__', new=new_init).start()
+
         self.queries = []
 
     def tearDown(self):
@@ -27,21 +49,6 @@ class DBQueryTestCase(unittest.TestCase):
     def reset_query(self):
         del self.queries[:]
 
-    def get_query(self, *args, **kwargs):
-        query = QP(*args, **kwargs)
-        query.execute = mock.MagicMock()
-        query.execute.return_value = self.qp_execute_return_value
-        query.execute.side_effect = self.qp_execute_side_effect
-        query.executeOne = mock.MagicMock()
-        query.executeOne.return_value = self.qp_execute_one_return_value
-        query.executeOne.side_effect = self.qp_execute_one_side_effect
-        query.singleValue = mock.MagicMock()
-        query.singleValue.return_value = self.qp_single_value_return_value
-        query.iterate = mock.MagicMock()
-        query.iterate.return_value = self.qp_iterate_return_value
-        self.queries.append(query)
-        return query
-
     def assertQueryEqual(self, query, **kwargs):
         for k, v in kwargs.items():
             self.assertEqual(getattr(query, k, None), v)

From c6272f2fd788a1b8f5f1ee367eddfe164ba4ca90 Mon Sep 17 00:00:00 2001
From: Mike McLean <mikem@redhat.com>
Date: Mar 29 2024 23:41:03 +0000
Subject: [PATCH 2/3] fix missing tearDown methods for numerous tests


---

diff --git a/tests/test_hub/test_add_group_member.py b/tests/test_hub/test_add_group_member.py
index 2925333..3dcb20b 100644
--- a/tests/test_hub/test_add_group_member.py
+++ b/tests/test_hub/test_add_group_member.py
@@ -12,6 +12,9 @@ class TestAddGroupMember(unittest.TestCase):
         self.exports = kojihub.RootExports()
         self.get_user = mock.patch('kojihub.kojihub.get_user').start()
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_non_exist_user(self):
         data = [{'id': 3,
                  'name': 'test-group',
diff --git a/tests/test_hub/test_add_volume.py b/tests/test_hub/test_add_volume.py
index de9023a..d92b08a 100644
--- a/tests/test_hub/test_add_volume.py
+++ b/tests/test_hub/test_add_volume.py
@@ -19,6 +19,9 @@ class TestAddVolume(unittest.TestCase):
         self.context.session.assertPerm = mock.MagicMock()
         self.context.session.assertLogin = mock.MagicMock()
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_add_volume_wrong_format(self):
         volume_name = 'volume-name+'
 
diff --git a/tests/test_hub/test_create_image_build.py b/tests/test_hub/test_create_image_build.py
index 2b881e1..864283a 100644
--- a/tests/test_hub/test_create_image_build.py
+++ b/tests/test_hub/test_create_image_build.py
@@ -18,6 +18,9 @@ class TestCreateImageBuild(unittest.TestCase):
         self.inserts = []
         self.insert_execute = mock.MagicMock()
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def getInsert(self, *args, **kwargs):
         insert = IP(*args, **kwargs)
         insert.execute = self.insert_execute
diff --git a/tests/test_hub/test_create_maven_build.py b/tests/test_hub/test_create_maven_build.py
index 8f13d43..53aa9fa 100644
--- a/tests/test_hub/test_create_maven_build.py
+++ b/tests/test_hub/test_create_maven_build.py
@@ -32,6 +32,9 @@ class TestCreateMavenBuild(unittest.TestCase):
         }
         self.build_info = 'test-build-11-12'
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def getInsert(self, *args, **kwargs):
         insert = IP(*args, **kwargs)
         insert.execute = self.insert_execute
diff --git a/tests/test_hub/test_create_user.py b/tests/test_hub/test_create_user.py
index 3f0dc05..00cf221 100644
--- a/tests/test_hub/test_create_user.py
+++ b/tests/test_hub/test_create_user.py
@@ -24,6 +24,9 @@ class TestCreateUser(unittest.TestCase):
         self.user_info_krb = {'id': 1, 'krb_principals': ['test_user@fedora.org'],
                               'name': self.user_name, 'status': 0, 'usertype': 0}
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_create_user_wrong_format(self):
         user_name = 'test-user+'
 
diff --git a/tests/test_hub/test_create_win_build.py b/tests/test_hub/test_create_win_build.py
index d714da6..3d2bbef 100644
--- a/tests/test_hub/test_create_win_build.py
+++ b/tests/test_hub/test_create_win_build.py
@@ -32,6 +32,9 @@ class TestCreateWinBuild(unittest.TestCase):
         }
         self.build_info = 'test-build-11-12'
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def getInsert(self, *args, **kwargs):
         insert = IP(*args, **kwargs)
         insert.execute = self.insert_execute
diff --git a/tests/test_hub/test_delete_build_target.py b/tests/test_hub/test_delete_build_target.py
index c90a68b..9b5c227 100644
--- a/tests/test_hub/test_delete_build_target.py
+++ b/tests/test_hub/test_delete_build_target.py
@@ -28,6 +28,9 @@ class TestDeleteBuildTarget(unittest.TestCase):
         # start with "assert"
         self.context_db.session.assertLogin = mock.MagicMock()
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_non_exist_target(self):
         build_target = 'build-target'
         self.lookup_build_target.return_value = None
diff --git a/tests/test_hub/test_disable_channel.py b/tests/test_hub/test_disable_channel.py
index 8aa35ce..fcb4595 100644
--- a/tests/test_hub/test_disable_channel.py
+++ b/tests/test_hub/test_disable_channel.py
@@ -24,6 +24,9 @@ class TestDisableChannel(unittest.TestCase):
         self.updates = []
         self.channelname = 'test-channel'
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_non_exist_channel(self):
         self.get_channel.return_value = None
         with self.assertRaises(koji.GenericError) as cm:
diff --git a/tests/test_hub/test_disable_user.py b/tests/test_hub/test_disable_user.py
index 4ee6574..94cb3a1 100644
--- a/tests/test_hub/test_disable_user.py
+++ b/tests/test_hub/test_disable_user.py
@@ -12,6 +12,9 @@ class TestDisableUser(unittest.TestCase):
         self.exports = kojihub.RootExports()
         self.get_user = mock.patch('kojihub.kojihub.get_user').start()
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_non_exist_user(self):
         username = 'test-user'
         self.get_user.return_value = None
diff --git a/tests/test_hub/test_edit_permission.py b/tests/test_hub/test_edit_permission.py
index 59c45c3..7a349a8 100644
--- a/tests/test_hub/test_edit_permission.py
+++ b/tests/test_hub/test_edit_permission.py
@@ -24,6 +24,9 @@ class TestEditPermission(unittest.TestCase):
         self.perm_info = {'id': 1, 'name': self.perm_name}
         self.description = 'test-description'
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_edit_permission_non_exist_permission(self):
         self.lookup_perm.side_effect = koji.GenericError
         with self.assertRaises(koji.GenericError):
diff --git a/tests/test_hub/test_enable_channel.py b/tests/test_hub/test_enable_channel.py
index 0fd12dd..183cb2e 100644
--- a/tests/test_hub/test_enable_channel.py
+++ b/tests/test_hub/test_enable_channel.py
@@ -24,6 +24,9 @@ class TestEnableChannel(unittest.TestCase):
         self.updates = []
         self.channelname = 'test-channel'
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_non_exist_channel(self):
 
         self.get_channel.return_value = None
diff --git a/tests/test_hub/test_enable_user.py b/tests/test_hub/test_enable_user.py
index 42bbd51..739a9d8 100644
--- a/tests/test_hub/test_enable_user.py
+++ b/tests/test_hub/test_enable_user.py
@@ -12,6 +12,9 @@ class TestEnableUser(unittest.TestCase):
         self.exports = kojihub.RootExports()
         self.get_user = mock.patch('kojihub.kojihub.get_user').start()
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_non_exist_user(self):
         username = 'test-user'
         self.get_user.return_value = None
diff --git a/tests/test_hub/test_find_build_id.py b/tests/test_hub/test_find_build_id.py
index 0c2f659..857985d 100644
--- a/tests/test_hub/test_find_build_id.py
+++ b/tests/test_hub/test_find_build_id.py
@@ -24,6 +24,9 @@ class TestFindBuildId(unittest.TestCase):
         self.queries = []
         self.query_singleValue = mock.MagicMock()
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_non_exist_build_dict(self):
         build = {
             'name': 'test_name',
diff --git a/tests/test_hub/test_getRPMDeps.py b/tests/test_hub/test_getRPMDeps.py
index ca1f317..53c50d5 100644
--- a/tests/test_hub/test_getRPMDeps.py
+++ b/tests/test_hub/test_getRPMDeps.py
@@ -11,6 +11,9 @@ class TestGetRPMDeps(unittest.TestCase):
         self.get_rpm = mock.patch('kojihub.kojihub.get_rpm').start()
         self.get_build = mock.patch('kojihub.kojihub.get_build').start()
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_getRPMDeps_no_rpminfo(self):
         def mock_get_rpm(rpmID, strict=False):
             if strict:
diff --git a/tests/test_hub/test_get_build_notifications.py b/tests/test_hub/test_get_build_notifications.py
index f8d023d..ce20126 100644
--- a/tests/test_hub/test_get_build_notifications.py
+++ b/tests/test_hub/test_get_build_notifications.py
@@ -10,6 +10,9 @@ class TestGetBuildNotifications(unittest.TestCase):
         self.get_user = mock.patch('kojihub.kojihub.get_user').start()
         self.get_build_notifications = mock.patch('kojihub.kojihub.get_build_notifications').start()
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_loggedin_user(self):
         self.get_user.return_value = {'id': 1}
         kojihub.RootExports().getBuildNotifications(None)
diff --git a/tests/test_hub/test_get_buildroot.py b/tests/test_hub/test_get_buildroot.py
index 7fd22f0..5fd8519 100644
--- a/tests/test_hub/test_get_buildroot.py
+++ b/tests/test_hub/test_get_buildroot.py
@@ -10,6 +10,9 @@ class TestGetBuildroot(unittest.TestCase):
         self.query_buildroots = mock.patch('kojihub.kojihub.query_buildroots').start()
         self.buildroot_id = 1
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_empty_buildroots_without_strict(self):
         self.query_buildroots.return_value = []
         rv = kojihub.get_buildroot(self.buildroot_id, strict=False)
diff --git a/tests/test_hub/test_get_changelog_entries.py b/tests/test_hub/test_get_changelog_entries.py
index d00aa17..0619e0a 100644
--- a/tests/test_hub/test_get_changelog_entries.py
+++ b/tests/test_hub/test_get_changelog_entries.py
@@ -17,6 +17,9 @@ class TestGetChangelogEntries(unittest.TestCase):
         self.cursor = mock.MagicMock()
         self.os_path_exists = mock.patch('os.path.exists').start()
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_non_exist_build(self):
         build_id = 1
         self.cursor.fetchone.return_value = None
diff --git a/tests/test_hub/test_get_external_repo.py b/tests/test_hub/test_get_external_repo.py
index b71070c..5b63edc 100644
--- a/tests/test_hub/test_get_external_repo.py
+++ b/tests/test_hub/test_get_external_repo.py
@@ -12,6 +12,9 @@ class TestGetExternalRepo(unittest.TestCase):
         self.get_external_repos = mock.patch('kojihub.kojihub.get_external_repos').start()
         self.exports = kojihub.RootExports()
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_non_exist_repo_with_strict(self):
         repo = 'test-repo'
         self.get_external_repos.return_value = []
diff --git a/tests/test_hub/test_get_next_release.py b/tests/test_hub/test_get_next_release.py
index 457e179..f199723 100644
--- a/tests/test_hub/test_get_next_release.py
+++ b/tests/test_hub/test_get_next_release.py
@@ -12,6 +12,9 @@ class TestGetNextRelease(DBQueryTestCase):
         self.get_build = mock.patch('kojihub.kojihub.get_build').start()
         self.binfo = {'name': 'name', 'version': 'version'}
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_get_next_release_new(self):
         # no previous build
         self.qp_execute_one_return_value = None
diff --git a/tests/test_hub/test_get_user.py b/tests/test_hub/test_get_user.py
index 51bcf2e..ba04035 100644
--- a/tests/test_hub/test_get_user.py
+++ b/tests/test_hub/test_get_user.py
@@ -15,6 +15,9 @@ class TestGetUser(DBQueryTestCase):
         self.list_user_krb_principals = mock.patch(
             'kojihub.kojihub.list_user_krb_principals').start()
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_wrong_format_user_info(self):
         userinfo = ['test-user']
         with self.assertRaises(koji.GenericError) as cm:
diff --git a/tests/test_hub/test_get_volume.py b/tests/test_hub/test_get_volume.py
index 3c17b1e..24a03b6 100644
--- a/tests/test_hub/test_get_volume.py
+++ b/tests/test_hub/test_get_volume.py
@@ -11,6 +11,9 @@ class TestGetVolume(unittest.TestCase):
         self.exports = kojihub.RootExports()
         self.lookup_name = mock.patch('kojihub.kojihub.lookup_name').start()
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_non_exist_volume_with_strict(self):
         volume = ['test-volume']
         self.lookup_name.return_value = None
diff --git a/tests/test_hub/test_grant_permissions.py b/tests/test_hub/test_grant_permissions.py
index 07afb97..c79f882 100644
--- a/tests/test_hub/test_grant_permissions.py
+++ b/tests/test_hub/test_grant_permissions.py
@@ -32,6 +32,9 @@ class TestGrantPermission(unittest.TestCase):
                          'status': 0, 'usertype': 0}
         self.perm_info = {'id': 1, 'name': self.perms_name}
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_grant_permission_wrong_format(self):
         perms_name = 'test-perms+'
 
diff --git a/tests/test_hub/test_group_pkg_operations.py b/tests/test_hub/test_group_pkg_operations.py
index 42a56d4..2304520 100644
--- a/tests/test_hub/test_group_pkg_operations.py
+++ b/tests/test_hub/test_group_pkg_operations.py
@@ -61,6 +61,9 @@ class TestGroupPkglist(unittest.TestCase):
         self.context_db.event_id = 42
         self.context_db.session.user_id = 24
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_grp_pkg_add_previous_changed(self):
         self.lookup_tag.return_value = self.taginfo
         self.lookup_group.return_value = self.groupinfo
diff --git a/tests/test_hub/test_group_req_operations.py b/tests/test_hub/test_group_req_operations.py
index 52251c5..dadf6e5 100644
--- a/tests/test_hub/test_group_req_operations.py
+++ b/tests/test_hub/test_group_req_operations.py
@@ -61,6 +61,9 @@ class TestGroupReqlist(unittest.TestCase):
         self.context_db.event_id = 42
         self.context_db.session.user_id = 24
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_grp_req_add_not_previous(self):
         self.lookup_tag.return_value = self.taginfo
         self.lookup_group.side_effect = [self.groupinfo, self.reqinfo]
diff --git a/tests/test_hub/test_import_image_internal.py b/tests/test_hub/test_import_image_internal.py
index a12d31e..435cb81 100644
--- a/tests/test_hub/test_import_image_internal.py
+++ b/tests/test_hub/test_import_image_internal.py
@@ -22,6 +22,7 @@ class TestImportImageInternal(unittest.TestCase):
 
     def tearDown(self):
         shutil.rmtree(self.tempdir)
+        mock.patch.stopall()
 
     def test_basic(self):
         task = mock.MagicMock()
diff --git a/tests/test_hub/test_list_builds.py b/tests/test_hub/test_list_builds.py
index 239a1dc..9456147 100644
--- a/tests/test_hub/test_list_builds.py
+++ b/tests/test_hub/test_list_builds.py
@@ -86,6 +86,9 @@ class TestListBuilds(unittest.TestCase):
                             'volume_name': 'DEFAULT',
                             'draft': False},]
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_wrong_package(self):
         package = 'test-package'
         self.get_package_id.return_value = None
diff --git a/tests/test_hub/test_list_tagged.py b/tests/test_hub/test_list_tagged.py
index 6cde73a..3990d69 100644
--- a/tests/test_hub/test_list_tagged.py
+++ b/tests/test_hub/test_list_tagged.py
@@ -27,6 +27,9 @@ class TestListTagged(unittest.TestCase):
              'release': '1.fc35', 'state': 1, 'tag_id': 1, 'tag_name': 'test-tag',
              'task_id': None, 'version': '2.52', 'volume_id': 0, 'volume_name': 'DEFAULT'}]
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def getQuery(self, *args, **kwargs):
         query = QP(*args, **kwargs)
         query.execute = mock.MagicMock()
diff --git a/tests/test_hub/test_list_tagged_archives.py b/tests/test_hub/test_list_tagged_archives.py
index 67c092c..2ccd469 100644
--- a/tests/test_hub/test_list_tagged_archives.py
+++ b/tests/test_hub/test_list_tagged_archives.py
@@ -48,6 +48,9 @@ class TestListTaggedArchives(unittest.TestCase):
               'volume_name': 'DEFAULT'}]
         ]
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def getQuery(self, *args, **kwargs):
         query = QP(*args, **kwargs)
         query.execute = mock.MagicMock()
diff --git a/tests/test_hub/test_list_tagged_rpms.py b/tests/test_hub/test_list_tagged_rpms.py
index 4a0e2e4..c93cc6a 100644
--- a/tests/test_hub/test_list_tagged_rpms.py
+++ b/tests/test_hub/test_list_tagged_rpms.py
@@ -47,6 +47,9 @@ class TestListTaggedRPMS(unittest.TestCase):
               'volume_name': 'DEFAULT'}]
         ]
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def getQuery(self, *args, **kwargs):
         query = QP(*args, **kwargs)
         query.execute = mock.MagicMock()
diff --git a/tests/test_hub/test_multicall.py b/tests/test_hub/test_multicall.py
index 5a9881a..3280b19 100644
--- a/tests/test_hub/test_multicall.py
+++ b/tests/test_hub/test_multicall.py
@@ -15,6 +15,9 @@ class DummyExports(object):
 
 class TestMulticall(unittest.TestCase):
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_multicall(self):
         self.context_db = mock.patch('kojihub.db.context').start()
         kojixmlrpc.kojihub = mock.MagicMock()
diff --git a/tests/test_hub/test_new_maven_build.py b/tests/test_hub/test_new_maven_build.py
index d84e4fe..f1636e8 100644
--- a/tests/test_hub/test_new_maven_build.py
+++ b/tests/test_hub/test_new_maven_build.py
@@ -26,6 +26,9 @@ class TestNewMavenBuild(unittest.TestCase):
             'build_id': 2,
         }
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def getInsert(self, *args, **kwargs):
         insert = IP(*args, **kwargs)
         insert.execute = self.insert_execute
diff --git a/tests/test_hub/test_new_win_build.py b/tests/test_hub/test_new_win_build.py
index f62f9a6..6813e54 100644
--- a/tests/test_hub/test_new_win_build.py
+++ b/tests/test_hub/test_new_win_build.py
@@ -31,6 +31,9 @@ class TestNewWinBuild(unittest.TestCase):
             'extra': {'extra_key': 'extra_value'},
         }
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def getInsert(self, *args, **kwargs):
         insert = IP(*args, **kwargs)
         insert.execute = self.insert_execute
diff --git a/tests/test_hub/test_query_buildroots.py b/tests/test_hub/test_query_buildroots.py
index 2257a55..019970e 100644
--- a/tests/test_hub/test_query_buildroots.py
+++ b/tests/test_hub/test_query_buildroots.py
@@ -20,6 +20,9 @@ class TestQueryBuildroots(unittest.TestCase):
         self.queries = []
         self.query_execute = mock.MagicMock()
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_query_buildroots(self):
         self.query_execute.side_effect = [[7], [7], [7], []]
         self.repo_references.return_value = [{'id': 7, 'host_id': 1, 'create_event': 333,
diff --git a/tests/test_hub/test_query_rpm_sigs.py b/tests/test_hub/test_query_rpm_sigs.py
index b993f55..2e19d74 100644
--- a/tests/test_hub/test_query_rpm_sigs.py
+++ b/tests/test_hub/test_query_rpm_sigs.py
@@ -35,6 +35,9 @@ class TestQueryRPMSigs(unittest.TestCase):
                       'size': 25644,
                       'version': '3.3'}
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_rpm_dict(self):
         rinfo_dict = {
             'arch': 'x86_64',
diff --git a/tests/test_hub/test_restart_hosts.py b/tests/test_hub/test_restart_hosts.py
index 005309a..4d0d8b1 100644
--- a/tests/test_hub/test_restart_hosts.py
+++ b/tests/test_hub/test_restart_hosts.py
@@ -14,6 +14,9 @@ class TestRestartHosts(unittest.TestCase):
         self.context.session.assertPerm = mock.MagicMock()
         self.make_task = mock.patch('kojihub.kojihub.make_task').start()
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_options_is_none(self):
         self.make_task.return_value = 13
         rv = self.exports.restartHosts()
diff --git a/tests/test_hub/test_set_user_status.py b/tests/test_hub/test_set_user_status.py
index 3455d55..e498834 100644
--- a/tests/test_hub/test_set_user_status.py
+++ b/tests/test_hub/test_set_user_status.py
@@ -23,6 +23,9 @@ class TestSetUserStatus(unittest.TestCase):
         self.context.session.assertPerm = mock.MagicMock()
         self.update_execute = mock.MagicMock()
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_wrong_status(self):
         status = 111
         with self.assertRaises(koji.GenericError) as cm:
diff --git a/tests/test_hub/test_verify_names.py b/tests/test_hub/test_verify_names.py
index 91901ad..c36e4c5 100644
--- a/tests/test_hub/test_verify_names.py
+++ b/tests/test_hub/test_verify_names.py
@@ -15,6 +15,9 @@ class TestVerifyNameInternal(unittest.TestCase):
         self.context.opts = {'MaxNameLengthInternal': 15,
                              'RegexNameInternal.compiled': re.compile('^[A-Za-z0-9/_.+-]+$')}
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_verify_name_internal_integer_type(self):
         expected_error = "Name should be string"
         with self.assertRaises(koji.GenericError) as cm:
diff --git a/tests/test_hub/utils.py b/tests/test_hub/utils.py
index f2e05c3..561e70a 100644
--- a/tests/test_hub/utils.py
+++ b/tests/test_hub/utils.py
@@ -28,7 +28,6 @@ def get_qp_init(testcase):
 class DBQueryTestCase(unittest.TestCase):
 
     def setUp(self):
-        mock.patch.stopall()
         self.qp_execute_return_value = []
         self.qp_execute_side_effect = None
         self.qp_execute_one_return_value = []
@@ -44,7 +43,6 @@ class DBQueryTestCase(unittest.TestCase):
 
     def tearDown(self):
         mock.patch.stopall()
-        self.reset_query()
 
     def reset_query(self):
         del self.queries[:]

From 25d65178640d830375860862d00be63f9bbef579 Mon Sep 17 00:00:00 2001
From: Mike McLean <mikem@redhat.com>
Date: Mar 30 2024 14:00:48 +0000
Subject: [PATCH 3/3] more missing tearDowns


---

diff --git a/tests/test_cli/test_add_channel.py b/tests/test_cli/test_add_channel.py
index 99f1ea1..0445e3d 100644
--- a/tests/test_cli/test_add_channel.py
+++ b/tests/test_cli/test_add_channel.py
@@ -26,6 +26,9 @@ class TestAddChannel(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     def test_handle_add_channel(self, stdout):
         self.session.addChannel.return_value = self.channel_id
diff --git a/tests/test_cli/test_add_external_repo.py b/tests/test_cli/test_add_external_repo.py
index afcccc6..24cabb4 100644
--- a/tests/test_cli/test_add_external_repo.py
+++ b/tests/test_cli/test_add_external_repo.py
@@ -25,6 +25,9 @@ class TestAddExternalRepo(utils.CliTestCase):
         self.tag = 'test-tag'
         self.priority = 10
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_add_external_repo_invalid_mode(self):
         mode = 'test-mode'
         arguments = ['--mode', mode]
diff --git a/tests/test_cli/test_add_group.py b/tests/test_cli/test_add_group.py
index 396f172..97622ef 100644
--- a/tests/test_cli/test_add_group.py
+++ b/tests/test_cli/test_add_group.py
@@ -21,6 +21,9 @@ class TestAddGroup(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     def test_handle_add_group(self, stdout):
         tag = 'tag'
diff --git a/tests/test_cli/test_add_host.py b/tests/test_cli/test_add_host.py
index 7a71469..12615b9 100644
--- a/tests/test_cli/test_add_host.py
+++ b/tests/test_cli/test_add_host.py
@@ -19,6 +19,9 @@ class TestAddHost(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     def test_handle_add_host(self, stdout):
         host = 'host'
diff --git a/tests/test_cli/test_add_host_to_channel.py b/tests/test_cli/test_add_host_to_channel.py
index eb4cb2a..9dce667 100644
--- a/tests/test_cli/test_add_host_to_channel.py
+++ b/tests/test_cli/test_add_host_to_channel.py
@@ -19,6 +19,9 @@ class TestAddHostToChannel(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     def test_handle_add_host_to_channel(self, stdout):
         host = 'host'
diff --git a/tests/test_cli/test_add_notification.py b/tests/test_cli/test_add_notification.py
index ff3c5ee..6e85bf4 100644
--- a/tests/test_cli/test_add_notification.py
+++ b/tests/test_cli/test_add_notification.py
@@ -21,6 +21,9 @@ class TestAddNotification(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_handle_add_notification(self):
         self.session.getPackageID.return_value = 1234
         self.session.getTagID.return_value = 4321
diff --git a/tests/test_cli/test_add_pkg.py b/tests/test_cli/test_add_pkg.py
index b876fa1..50739da 100644
--- a/tests/test_cli/test_add_pkg.py
+++ b/tests/test_cli/test_add_pkg.py
@@ -27,6 +27,9 @@ class TestAddPkg(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     def test_handle_add_pkg(self, stdout):
         tag = 'tag'
diff --git a/tests/test_cli/test_add_tag.py b/tests/test_cli/test_add_tag.py
index c5d8640..5b7b2dd 100644
--- a/tests/test_cli/test_add_tag.py
+++ b/tests/test_cli/test_add_tag.py
@@ -21,6 +21,9 @@ class TestAddTag(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_handle_add_tag(self):
         """Test handle_add_tag function"""
         # Case 1. no argument error
diff --git a/tests/test_cli/test_add_tag_inheritance.py b/tests/test_cli/test_add_tag_inheritance.py
index fe5cd32..892be39 100644
--- a/tests/test_cli/test_add_tag_inheritance.py
+++ b/tests/test_cli/test_add_tag_inheritance.py
@@ -56,6 +56,9 @@ class TestAddTagInheritance(utils.CliTestCase):
                       'perm': None,
                       'perm_id': None}
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_add_tag_inheritance_without_option(self):
         arguments = []
         expected = self.format_error_message(
diff --git a/tests/test_cli/test_add_target.py b/tests/test_cli/test_add_target.py
index a453cdc..78aa924 100644
--- a/tests/test_cli/test_add_target.py
+++ b/tests/test_cli/test_add_target.py
@@ -20,6 +20,9 @@ class TestAddTarget(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_add_target_without_option(self,):
         expected = self.format_error_message(
             "Please specify a target name, a build tag, and destination tag")
diff --git a/tests/test_cli/test_add_user.py b/tests/test_cli/test_add_user.py
index a7099d7..afea994 100644
--- a/tests/test_cli/test_add_user.py
+++ b/tests/test_cli/test_add_user.py
@@ -25,6 +25,9 @@ class TestAddUser(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     def test_handle_add_user(self, stdout):
         """Test handle_add_user function"""
diff --git a/tests/test_cli/test_add_volume.py b/tests/test_cli/test_add_volume.py
index 5fa8436..ca4f740 100644
--- a/tests/test_cli/test_add_volume.py
+++ b/tests/test_cli/test_add_volume.py
@@ -24,6 +24,9 @@ class TestAddVolume(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     def test_handle_add_volume(self, stdout):
         """Test handle_add_volume function"""
diff --git a/tests/test_cli/test_assign_task.py b/tests/test_cli/test_assign_task.py
index ed38f48..ed9f62c 100644
--- a/tests/test_cli/test_assign_task.py
+++ b/tests/test_cli/test_assign_task.py
@@ -24,6 +24,9 @@ class TestAssignTask(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     def test_handle_assign_task(self, stdout):
         hostname = "host"
diff --git a/tests/test_cli/test_block_group.py b/tests/test_cli/test_block_group.py
index 51345a5..f483108 100644
--- a/tests/test_cli/test_block_group.py
+++ b/tests/test_cli/test_block_group.py
@@ -25,6 +25,9 @@ class TestBlockGroup(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_handle_block_group_nonexistent_tag(self):
         tag = 'nonexistent-tag'
         group = 'group'
diff --git a/tests/test_cli/test_block_notification.py b/tests/test_cli/test_block_notification.py
index a1107a5..25c1ca4 100644
--- a/tests/test_cli/test_block_notification.py
+++ b/tests/test_cli/test_block_notification.py
@@ -21,6 +21,9 @@ class TestBlockNotification(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_handle_block_notification_non_exist_tag(self):
         tag = 'test-tag'
         arguments = ['--tag', tag]
diff --git a/tests/test_cli/test_block_pkg.py b/tests/test_cli/test_block_pkg.py
index f637adb..750b823 100644
--- a/tests/test_cli/test_block_pkg.py
+++ b/tests/test_cli/test_block_pkg.py
@@ -26,6 +26,9 @@ class TestBlockPkg(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     def test_handle_block_pkg(self, stdout):
         tag = 'tag'
diff --git a/tests/test_cli/test_build.py b/tests/test_cli/test_build.py
index b66d391..215a577 100644
--- a/tests/test_cli/test_build.py
+++ b/tests/test_cli/test_build.py
@@ -48,6 +48,9 @@ https://docs.pagure.org/koji/HOWTO/#package-organization
 %s: error: {message}
 """ % (self.progname, self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     def test_handle_build_from_srpm(self, stdout):
         args = [self.target, self.source_srpm]
diff --git a/tests/test_cli/test_call.py b/tests/test_cli/test_call.py
index 727fefc..378849b 100644
--- a/tests/test_cli/test_call.py
+++ b/tests/test_cli/test_call.py
@@ -29,6 +29,9 @@ Note, that you can use global option --noauth for anonymous calls here
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     def test_handle_call(self, stdout):
         """Test handle_call function"""
diff --git a/tests/test_cli/test_cancel.py b/tests/test_cli/test_cancel.py
index 7a8a1c6..580165c 100644
--- a/tests/test_cli/test_cancel.py
+++ b/tests/test_cli/test_cancel.py
@@ -35,6 +35,9 @@ class TestCancel(utils.CliTestCase):
         self.session.hub_version = (1, 33, 0)
         self.session.hub_version_str = '1.33.0'
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_anon_cancel(self):
         args = ['123']
         self.activate_session_mock.side_effect = koji.GenericError
diff --git a/tests/test_cli/test_chain_build.py b/tests/test_cli/test_chain_build.py
index 8238366..f5dd01b 100644
--- a/tests/test_cli/test_chain_build.py
+++ b/tests/test_cli/test_chain_build.py
@@ -31,6 +31,9 @@ class TestChainBuild(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     def test_handle_chain_build(self, stdout):
         target = 'target'
diff --git a/tests/test_cli/test_disable_channel.py b/tests/test_cli/test_disable_channel.py
index a0aeaf7..03b3d96 100644
--- a/tests/test_cli/test_disable_channel.py
+++ b/tests/test_cli/test_disable_channel.py
@@ -29,6 +29,9 @@ class TestDisableChannel(utils.CliTestCase):
              'name': 'test-channel'}
         ]
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def __vm(self, result):
         m = koji.VirtualCall('mcall_method', [], {})
         if isinstance(result, dict) and result.get('faultCode'):
diff --git a/tests/test_cli/test_disable_host.py b/tests/test_cli/test_disable_host.py
index 1dbc154..a101c29 100644
--- a/tests/test_cli/test_disable_host.py
+++ b/tests/test_cli/test_disable_host.py
@@ -21,6 +21,9 @@ class TestDisableHost(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_handle_disable_host_no_such_host(self):
         """Test %s function""" % handle_disable_host.__name__
         self.session.getHost.return_value = None
diff --git a/tests/test_cli/test_disable_user.py b/tests/test_cli/test_disable_user.py
index ff54eec..7e21d22 100644
--- a/tests/test_cli/test_disable_user.py
+++ b/tests/test_cli/test_disable_user.py
@@ -24,6 +24,9 @@ class TestDisableUser(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_handle_disable_user_no_argument(self):
         """Test handle_disable_user function"""
         expected = self.format_error_message(
diff --git a/tests/test_cli/test_edit_external_repo.py b/tests/test_cli/test_edit_external_repo.py
index 10a8f1e..8cd2210 100644
--- a/tests/test_cli/test_edit_external_repo.py
+++ b/tests/test_cli/test_edit_external_repo.py
@@ -24,6 +24,9 @@ class TestEditExternalRepo(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_handle_edit_external_repo_error(self):
         """Test handle_edit_external_repo function"""
         # [(expected, args),...]
diff --git a/tests/test_cli/test_edit_host.py b/tests/test_cli/test_edit_host.py
index b7cca31..7f6cf68 100644
--- a/tests/test_cli/test_edit_host.py
+++ b/tests/test_cli/test_edit_host.py
@@ -28,6 +28,9 @@ class TestEditHost(utils.CliTestCase):
         self.description = 'description'
         self.comment = 'comment'
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     def test_handle_edit_host(self, stdout):
         host_info = mock.ANY
diff --git a/tests/test_cli/test_edit_notification.py b/tests/test_cli/test_edit_notification.py
index 889335d..09954dc 100644
--- a/tests/test_cli/test_edit_notification.py
+++ b/tests/test_cli/test_edit_notification.py
@@ -19,6 +19,9 @@ class TestEditNotification(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_handle_edit_notification(self):
         self.session.getPackageID.return_value = 1234
         self.session.getTagID.return_value = 4321
diff --git a/tests/test_cli/test_edit_permission.py b/tests/test_cli/test_edit_permission.py
index 0d9a104..c03462f 100644
--- a/tests/test_cli/test_edit_permission.py
+++ b/tests/test_cli/test_edit_permission.py
@@ -26,6 +26,9 @@ class TestEditPermission(utils.CliTestCase):
         self.perm = 'test-perm'
         self.description = 'test-description'
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_handle_edit_permission_argument_error(self):
         expected = self.format_error_message("Please specify a permission and a description")
         for args in [[], [self.perm]]:
diff --git a/tests/test_cli/test_edit_tag.py b/tests/test_cli/test_edit_tag.py
index 19e302d..ae6661f 100644
--- a/tests/test_cli/test_edit_tag.py
+++ b/tests/test_cli/test_edit_tag.py
@@ -30,6 +30,9 @@ class TestEditTag(utils.CliTestCase):
         self.extra = {'extraA': 'A', 'extraB': True}
         self.remove_extra = ['extraC', 'extraD']
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     def test_handle_edit_tag_1(self, stdout):
         args = [self.tag]
diff --git a/tests/test_cli/test_edit_target.py b/tests/test_cli/test_edit_target.py
index 34a449d..57a6c53 100644
--- a/tests/test_cli/test_edit_target.py
+++ b/tests/test_cli/test_edit_target.py
@@ -42,6 +42,9 @@ class TestEditTarget(utils.CliTestCase):
         self.new_dest_tag = 'new-dest-tag'
         self.new_build_tag = 'new-build-tag'
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_edit_target_without_option(self):
         expected = self.format_error_message("Please specify a build target")
         self.assert_system_exit(
diff --git a/tests/test_cli/test_edit_user.py b/tests/test_cli/test_edit_user.py
index 0b5784a..1bc31ed 100644
--- a/tests/test_cli/test_edit_user.py
+++ b/tests/test_cli/test_edit_user.py
@@ -26,6 +26,9 @@ class TestEditUser(utils.CliTestCase):
         self.user = 'user'
         self.rename = 'user2'
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     def test_handle_edit_user(self, stdout):
         args = [self.user]
diff --git a/tests/test_cli/test_enable_channel.py b/tests/test_cli/test_enable_channel.py
index 2c985e2..f1243e1 100644
--- a/tests/test_cli/test_enable_channel.py
+++ b/tests/test_cli/test_enable_channel.py
@@ -30,6 +30,9 @@ class TestEnableChannel(utils.CliTestCase):
              'name': 'test-channel'}
         ]
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def __vm(self, result):
         m = koji.VirtualCall('mcall_method', [], {})
         if isinstance(result, dict) and result.get('faultCode'):
diff --git a/tests/test_cli/test_enable_host.py b/tests/test_cli/test_enable_host.py
index 276f692..bb9721e 100644
--- a/tests/test_cli/test_enable_host.py
+++ b/tests/test_cli/test_enable_host.py
@@ -22,6 +22,9 @@ class TestEnableHost(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_handle_enable_host_no_such_host(self):
         """Test %s function""" % handle_enable_host.__name__
 
diff --git a/tests/test_cli/test_enable_user.py b/tests/test_cli/test_enable_user.py
index 58ce95c..9438ef0 100644
--- a/tests/test_cli/test_enable_user.py
+++ b/tests/test_cli/test_enable_user.py
@@ -21,6 +21,9 @@ class TestEnableUser(utils.CliTestCase):
 """ % (self.progname, self.progname)
         self.username = 'user'
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_handle_enable_user_no_argument(self):
         """Test handle_enable_user function"""
         expected = self.format_error_message("You must specify the username of the user to enable")
diff --git a/tests/test_cli/test_free_task.py b/tests/test_cli/test_free_task.py
index 705afb6..5e1f40f 100644
--- a/tests/test_cli/test_free_task.py
+++ b/tests/test_cli/test_free_task.py
@@ -19,6 +19,9 @@ class TestFreeTask(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_free_task_without_arg(self):
         expected = self.format_error_message('please specify at least one task_id')
         self.assert_system_exit(
diff --git a/tests/test_cli/test_grant_cg_access.py b/tests/test_cli/test_grant_cg_access.py
index ed71eb3..d2ba71b 100644
--- a/tests/test_cli/test_grant_cg_access.py
+++ b/tests/test_cli/test_grant_cg_access.py
@@ -22,6 +22,9 @@ class TestGrantCGAccess(utils.CliTestCase):
         self.cg = 'cg'
         self.user = 'user'
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_handle_grant_cg_access_arg_error(self):
         """Test handle_grant_cg_access function"""
         expected = self.format_error_message("Please specify a user and content generator")
diff --git a/tests/test_cli/test_grant_permission.py b/tests/test_cli/test_grant_permission.py
index d70e9aa..f5df6ef 100644
--- a/tests/test_cli/test_grant_permission.py
+++ b/tests/test_cli/test_grant_permission.py
@@ -26,6 +26,9 @@ class TestGrantPermission(utils.CliTestCase):
         self.perm = 'createuser'
         self.user = 'user'
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_handle_grant_permission_argument_error(self):
         expected = self.format_error_message(
             "Please specify a permission and at least one user")
diff --git a/tests/test_cli/test_hello.py b/tests/test_cli/test_hello.py
index 6e35638..079e68c 100644
--- a/tests/test_cli/test_hello.py
+++ b/tests/test_cli/test_hello.py
@@ -39,6 +39,9 @@ class TestHello(utils.CliTestCase):
 """ % (self.progname, self.progname)
         self.huburl = "https://%s.local/%shub" % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands._printable_unicode')
     def test_handle_moshimoshi(self, print_unicode_mock, stdout):
diff --git a/tests/test_cli/test_import.py b/tests/test_cli/test_import.py
index e91a5a7..381efad 100644
--- a/tests/test_cli/test_import.py
+++ b/tests/test_cli/test_import.py
@@ -84,6 +84,9 @@ class TestImport(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def __do_import_test(self, options, session, arguments, **kwargs):
         expected = kwargs.get('expected', None)
         rpm_header = kwargs.get('rpm_header', {})
diff --git a/tests/test_cli/test_import_archive.py b/tests/test_cli/test_import_archive.py
index dbdfe6b..b6f0706 100644
--- a/tests/test_cli/test_import_archive.py
+++ b/tests/test_cli/test_import_archive.py
@@ -23,6 +23,9 @@ class TestImportArchive(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_import_archive_without_option(self):
         expected = self.format_error_message(
             "You must specify a build ID or N-V-R and an archive to import")
diff --git a/tests/test_cli/test_import_cg.py b/tests/test_cli/test_import_cg.py
index 3854702..852945a 100644
--- a/tests/test_cli/test_import_cg.py
+++ b/tests/test_cli/test_import_cg.py
@@ -34,6 +34,9 @@ class TestImportCG(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands._progress_callback')
     @mock.patch('koji.json')
diff --git a/tests/test_cli/test_import_comps.py b/tests/test_cli/test_import_comps.py
index 466b0fd..de2f82f 100644
--- a/tests/test_cli/test_import_comps.py
+++ b/tests/test_cli/test_import_comps.py
@@ -38,6 +38,9 @@ class TestImportComps(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands.libcomps')
     @mock.patch('koji_cli.commands._import_comps')
diff --git a/tests/test_cli/test_import_sig.py b/tests/test_cli/test_import_sig.py
index 12041fc..2f1519a 100644
--- a/tests/test_cli/test_import_sig.py
+++ b/tests/test_cli/test_import_sig.py
@@ -76,6 +76,9 @@ class TestImportSIG(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stderr', new_callable=six.StringIO)
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('koji.rip_rpm_sighdr')
diff --git a/tests/test_cli/test_list_api.py b/tests/test_cli/test_list_api.py
index 59606cf..3d007ca 100644
--- a/tests/test_cli/test_list_api.py
+++ b/tests/test_cli/test_list_api.py
@@ -19,6 +19,9 @@ class TestListApi(utils.CliTestCase):
         self.options = mock.MagicMock()
         self.ensure_connection = mock.patch('koji_cli.commands.ensure_connection').start()
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     def test_anon_handle_list_api_all_method(self, stdout):
         """Test anon_handle_list_api function"""
diff --git a/tests/test_cli/test_list_buildroot.py b/tests/test_cli/test_list_buildroot.py
index 7b4b6ce..89e7b61 100644
--- a/tests/test_cli/test_list_buildroot.py
+++ b/tests/test_cli/test_list_buildroot.py
@@ -22,6 +22,9 @@ class TestListBuilds(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_list_buildroot_without_args(self):
         self.assert_system_exit(
             anon_handle_list_buildroot,
diff --git a/tests/test_cli/test_list_channels.py b/tests/test_cli/test_list_channels.py
index 2d28b89..747ebed 100644
--- a/tests/test_cli/test_list_channels.py
+++ b/tests/test_cli/test_list_channels.py
@@ -64,6 +64,9 @@ class TestListChannels(utils.CliTestCase):
             ]]
         ]
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stdout', new_callable=StringIO)
     def test_list_channels_not_quiet(self, stdout):
         self.session.listChannels.return_value = self.list_channels
diff --git a/tests/test_cli/test_list_notifications.py b/tests/test_cli/test_list_notifications.py
index 5e7869d..ef8f643 100644
--- a/tests/test_cli/test_list_notifications.py
+++ b/tests/test_cli/test_list_notifications.py
@@ -23,6 +23,9 @@ class TestListNotifications(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stdout', new_callable=StringIO)
     def test_list_notifications(self, stdout):
         self.session.getBuildNotifications.return_value = [
diff --git a/tests/test_cli/test_list_permissions.py b/tests/test_cli/test_list_permissions.py
index d9dc077..9fb5157 100644
--- a/tests/test_cli/test_list_permissions.py
+++ b/tests/test_cli/test_list_permissions.py
@@ -36,6 +36,9 @@ class TestListPermissions(utils.CliTestCase):
         self.user = 'tester'
         self.userinfo = {'id': 101, 'name': self.user}
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_handle_list_permissions_arg_error(self):
         """Test handle_list_permissions argument error (no argument is required)"""
         expected = self.format_error_message("This command takes no arguments")
diff --git a/tests/test_cli/test_list_pkgs.py b/tests/test_cli/test_list_pkgs.py
index 307c783..cf4a88c 100644
--- a/tests/test_cli/test_list_pkgs.py
+++ b/tests/test_cli/test_list_pkgs.py
@@ -52,6 +52,9 @@ class TestListPkgs(utils.CliTestCase):
                         'perm': None,
                         'perm_id': None}
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_list_pkgs_non_exist_tag(self):
         self.session.getTag.return_value = None
         self.assert_system_exit(
diff --git a/tests/test_cli/test_list_signed.py b/tests/test_cli/test_list_signed.py
index 1f8b069..9be5e43 100644
--- a/tests/test_cli/test_list_signed.py
+++ b/tests/test_cli/test_list_signed.py
@@ -20,6 +20,9 @@ class TestListSigned(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def __vm(self, result):
         m = koji.VirtualCall('mcall_method', [], {})
         if isinstance(result, dict) and result.get('faultCode'):
diff --git a/tests/test_cli/test_list_tags.py b/tests/test_cli/test_list_tags.py
index 023feb3..aa8f59c 100644
--- a/tests/test_cli/test_list_tags.py
+++ b/tests/test_cli/test_list_tags.py
@@ -38,6 +38,9 @@ class TestListTags(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_list_tags_non_exist_package(self):
         pkg = 'test-pkg'
         self.session.getPackage.return_value = None
diff --git a/tests/test_cli/test_mock_config.py b/tests/test_cli/test_mock_config.py
index cc7fd60..9f58ad0 100644
--- a/tests/test_cli/test_mock_config.py
+++ b/tests/test_cli/test_mock_config.py
@@ -65,6 +65,9 @@ config_opts['macros']['%distribution'] = 'Koji Testing'
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     def test_handle_mock_config_buildroot_option(self, stdout):
         """Test anon_handle_mock_config buildroot options"""
diff --git a/tests/test_cli/test_remove_external_repo.py b/tests/test_cli/test_remove_external_repo.py
index 25d1847..268b07e 100644
--- a/tests/test_cli/test_remove_external_repo.py
+++ b/tests/test_cli/test_remove_external_repo.py
@@ -18,6 +18,9 @@ class TestRemoveExternalRepo(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_remove_external_repo_help(self):
         self.assert_help(
             handle_remove_external_repo,
diff --git a/tests/test_cli/test_remove_pkg.py b/tests/test_cli/test_remove_pkg.py
index 04f9076..8d28c6b 100644
--- a/tests/test_cli/test_remove_pkg.py
+++ b/tests/test_cli/test_remove_pkg.py
@@ -28,6 +28,9 @@ class TestRemovePkg(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stderr', new_callable=six.StringIO)
     def test_handle_remove_pkg(self, stderr):
         tag = 'tag'
diff --git a/tests/test_cli/test_remove_tag_inheritance.py b/tests/test_cli/test_remove_tag_inheritance.py
index dd02d26..a0c261d 100644
--- a/tests/test_cli/test_remove_tag_inheritance.py
+++ b/tests/test_cli/test_remove_tag_inheritance.py
@@ -50,6 +50,9 @@ class TestRemoveTagInheritance(utils.CliTestCase):
                                 'perm': None,
                                 'perm_id': None}
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_remove_tag_inheritance_without_option(self):
         expected = self.format_error_message(
             "This command takes at least one argument: a tag name or ID")
diff --git a/tests/test_cli/test_restart_host.py b/tests/test_cli/test_restart_host.py
index 7801148..4d81b29 100644
--- a/tests/test_cli/test_restart_host.py
+++ b/tests/test_cli/test_restart_host.py
@@ -24,6 +24,9 @@ class TestRestartHosts(utils.CliTestCase):
         self.watch_tasks_mock = mock.patch('koji_cli.commands.watch_tasks').start()
         self.task_id = 101
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_handle_restart_hosts_force_options(self):
         """Test %s function with --force option""" % handle_restart_hosts.__name__
         arguments = ['--force']
diff --git a/tests/test_cli/test_set_task_priority.py b/tests/test_cli/test_set_task_priority.py
index fb2c23a..dda93d3 100644
--- a/tests/test_cli/test_set_task_priority.py
+++ b/tests/test_cli/test_set_task_priority.py
@@ -25,6 +25,9 @@ class TestSetTaskPriority(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('sys.stderr', new_callable=six.StringIO)
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     def test_handle_set_task_priority(self, stdout, stderr):
diff --git a/tests/test_cli/test_show_groups.py b/tests/test_cli/test_show_groups.py
index 73e6deb..15ef148 100644
--- a/tests/test_cli/test_show_groups.py
+++ b/tests/test_cli/test_show_groups.py
@@ -52,6 +52,9 @@ class TestShowGroups(utils.CliTestCase):
              'group_id': 3}
         ]
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_show_groups_incorrect_num_of_args(self):
         arguments = []
         self.assert_system_exit(
diff --git a/tests/test_cli/test_untag_build.py b/tests/test_cli/test_untag_build.py
index e1c42c6..5d2d6ca 100644
--- a/tests/test_cli/test_untag_build.py
+++ b/tests/test_cli/test_untag_build.py
@@ -34,6 +34,9 @@ class TestUntagBuild(utils.CliTestCase):
                               'name': 'test-package', 'release': '1.f35', 'tag.name': 'test-tag',
                               'tag_id': 460, 'version': '1.1'}]}
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def __vm(self, result):
         m = koji.VirtualCall('mcall_method', [], {})
         if isinstance(result, dict) and result.get('faultCode'):
diff --git a/tests/test_cli/test_watch_logs.py b/tests/test_cli/test_watch_logs.py
index 0e304cd..2463067 100644
--- a/tests/test_cli/test_watch_logs.py
+++ b/tests/test_cli/test_watch_logs.py
@@ -21,6 +21,9 @@ class TestWatchLogs(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_handle_watch_logs_help(self):
         self.assert_help(
             anon_handle_watch_logs,
diff --git a/tests/test_cli/test_win_build.py b/tests/test_cli/test_win_build.py
index bb66f59..bac4a67 100644
--- a/tests/test_cli/test_win_build.py
+++ b/tests/test_cli/test_win_build.py
@@ -39,6 +39,9 @@ class TestWinBuild(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_win_build_without_option(self):
         self.assert_system_exit(
             handle_win_build,
diff --git a/tests/test_hub/test_get_next_release.py b/tests/test_hub/test_get_next_release.py
index f199723..457e179 100644
--- a/tests/test_hub/test_get_next_release.py
+++ b/tests/test_hub/test_get_next_release.py
@@ -12,9 +12,6 @@ class TestGetNextRelease(DBQueryTestCase):
         self.get_build = mock.patch('kojihub.kojihub.get_build').start()
         self.binfo = {'name': 'name', 'version': 'version'}
 
-    def tearDown(self):
-        mock.patch.stopall()
-
     def test_get_next_release_new(self):
         # no previous build
         self.qp_execute_one_return_value = None
diff --git a/tests/test_hub/test_get_user.py b/tests/test_hub/test_get_user.py
index ba04035..51bcf2e 100644
--- a/tests/test_hub/test_get_user.py
+++ b/tests/test_hub/test_get_user.py
@@ -15,9 +15,6 @@ class TestGetUser(DBQueryTestCase):
         self.list_user_krb_principals = mock.patch(
             'kojihub.kojihub.list_user_krb_principals').start()
 
-    def tearDown(self):
-        mock.patch.stopall()
-
     def test_wrong_format_user_info(self):
         userinfo = ['test-user']
         with self.assertRaises(koji.GenericError) as cm:
diff --git a/tests/test_hub/test_models/test_host.py b/tests/test_hub/test_models/test_host.py
index 248c936..80daa53 100644
--- a/tests/test_hub/test_models/test_host.py
+++ b/tests/test_hub/test_models/test_host.py
@@ -32,6 +32,9 @@ class TestHost(unittest.TestCase):
         self.queries = []
         self.query_execute = mock.MagicMock()
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('kojihub.kojihub.context')
     def test_instantiation_not_a_host(self, context):
         context.session.getHostId.return_value = None
diff --git a/tests/test_hub/test_verify_names.py b/tests/test_hub/test_verify_names.py
index c36e4c5..2fcc397 100644
--- a/tests/test_hub/test_verify_names.py
+++ b/tests/test_hub/test_verify_names.py
@@ -46,6 +46,9 @@ class TestVerifyUser(unittest.TestCase):
         self.context.opts = {'MaxNameLengthInternal': 15,
                              'RegexUserName.compiled': re.compile('^[A-Za-z0-9/_.@-]+$')}
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_verify_user_type_name(self):
         expected_error = "Name should be string"
         with self.assertRaises(koji.GenericError) as cm:
diff --git a/tests/test_lib/test_auth.py b/tests/test_lib/test_auth.py
index a8672df..f385b91 100644
--- a/tests/test_lib/test_auth.py
+++ b/tests/test_lib/test_auth.py
@@ -44,6 +44,9 @@ class TestAuthSession(unittest.TestCase):
         # start with "assert"
         self.context.session.assertLogin = mock.MagicMock()
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     def test_instance(self):
         """Simple kojihub.auth.Session instance"""
         self.context.opts = {

