diff --git a/lib/config/presets/bitbucket-server/index.spec.ts b/lib/config/presets/bitbucket-server/index.spec.ts
index 4aaad95f332645b9929727998d5b0cdae19d3986..87bae5b5d7cd2eeffa9b02bb0c29565ca77b8768 100644
--- a/lib/config/presets/bitbucket-server/index.spec.ts
+++ b/lib/config/presets/bitbucket-server/index.spec.ts
@@ -13,12 +13,9 @@ const basePath = '/rest/api/1.0/projects/some/repos/repo/browse';
 
 describe(getName(), () => {
   beforeEach(() => {
-    httpMock.setup();
     hostRules.find.mockReturnValue({ token: 'abc' });
   });
 
-  afterEach(() => httpMock.reset());
-
   describe('fetchJSONFile()', () => {
     it('returns JSON', async () => {
       httpMock
diff --git a/lib/config/presets/bitbucket/index.spec.ts b/lib/config/presets/bitbucket/index.spec.ts
index cf26c9410dbfcd15d56d4f07358d5ec406cdf739..7a69e16f7e6cbef6a631af9bf1eb6c8cf88fdafa 100644
--- a/lib/config/presets/bitbucket/index.spec.ts
+++ b/lib/config/presets/bitbucket/index.spec.ts
@@ -14,14 +14,6 @@ describe(getName(), () => {
     setPlatformApi('bitbucket');
   });
 
-  beforeEach(() => {
-    httpMock.setup();
-  });
-
-  afterEach(() => {
-    httpMock.reset();
-  });
-
   describe('fetchJSONFile()', () => {
     it('returns JSON', async () => {
       const data = { foo: 'bar' };
diff --git a/lib/config/presets/gitea/index.spec.ts b/lib/config/presets/gitea/index.spec.ts
index 5582056521e852d3cc142b5c2e3aed1b95f88eae..1e706c652686f6803fd736a22ce94491b09eb23e 100644
--- a/lib/config/presets/gitea/index.spec.ts
+++ b/lib/config/presets/gitea/index.spec.ts
@@ -14,13 +14,10 @@ const basePath = '/repos/some/repo/contents';
 
 describe(getName(), () => {
   beforeEach(() => {
-    httpMock.setup();
     hostRules.find.mockReturnValue({ token: 'abc' });
     setBaseUrl(giteaApiHost);
   });
 
-  afterEach(() => httpMock.reset());
-
   describe('fetchJSONFile()', () => {
     it('returns JSON', async () => {
       httpMock
diff --git a/lib/config/presets/github/index.spec.ts b/lib/config/presets/github/index.spec.ts
index 9e2fffdca405e8c3501a72256928a1c55e8d826e..e7b45b1684122dcf12e693b62d97967a5fdd1585 100644
--- a/lib/config/presets/github/index.spec.ts
+++ b/lib/config/presets/github/index.spec.ts
@@ -13,12 +13,9 @@ const basePath = '/repos/some/repo/contents';
 
 describe(getName(), () => {
   beforeEach(() => {
-    httpMock.setup();
     hostRules.find.mockReturnValue({ token: 'abc' });
   });
 
-  afterEach(() => httpMock.reset());
-
   describe('fetchJSONFile()', () => {
     it('returns JSON', async () => {
       httpMock
diff --git a/lib/config/presets/gitlab/index.spec.ts b/lib/config/presets/gitlab/index.spec.ts
index 53d32d88bf09f5c9dde994a4c51f442712e1ea15..b100dc70f5efcb0740848f5636b9c9c509f12def 100644
--- a/lib/config/presets/gitlab/index.spec.ts
+++ b/lib/config/presets/gitlab/index.spec.ts
@@ -10,11 +10,6 @@ const basePath = '/api/v4/projects/some%2Frepo/repository';
 describe(getName(), () => {
   beforeEach(() => {
     jest.resetAllMocks();
-    httpMock.setup();
-  });
-
-  afterEach(() => {
-    httpMock.reset();
   });
 
   describe('getPreset()', () => {
diff --git a/lib/datasource/bitbucket-tags/index.spec.ts b/lib/datasource/bitbucket-tags/index.spec.ts
index ab7b800cf490c5bf3a95e2a2d45a4cb2d1f5fbf8..83290ddd9b53576dda59887db37128c1a1c6d43b 100644
--- a/lib/datasource/bitbucket-tags/index.spec.ts
+++ b/lib/datasource/bitbucket-tags/index.spec.ts
@@ -4,13 +4,6 @@ import { getName } from '../../../test/util';
 import { id as datasource } from '.';
 
 describe(getName(), () => {
-  beforeEach(() => {
-    httpMock.reset();
-    httpMock.setup();
-  });
-  afterEach(() => {
-    httpMock.reset();
-  });
   describe('getReleases', () => {
     it('returns tags from bitbucket cloud', async () => {
       const body = {
diff --git a/lib/datasource/cdnjs/index.spec.ts b/lib/datasource/cdnjs/index.spec.ts
index d81e627fbc4d5c8d5002209bb6565ee5d214ed6e..c7aed56bcd1581bec21c6ff5be5456f2e4955b7c 100644
--- a/lib/datasource/cdnjs/index.spec.ts
+++ b/lib/datasource/cdnjs/index.spec.ts
@@ -16,11 +16,6 @@ describe(getName(), () => {
   describe('getReleases', () => {
     beforeEach(() => {
       jest.clearAllMocks();
-      httpMock.setup();
-    });
-
-    afterEach(() => {
-      httpMock.reset();
     });
 
     it('throws for empty result', async () => {
diff --git a/lib/datasource/clojure/index.spec.ts b/lib/datasource/clojure/index.spec.ts
index 5285ec397c6ce0841654b5db1f307a38730d9d3a..c9c1e7ccc83e58bd92a47734689030a6d0993154 100644
--- a/lib/datasource/clojure/index.spec.ts
+++ b/lib/datasource/clojure/index.spec.ts
@@ -90,12 +90,10 @@ describe(getName(), () => {
       token: 'abc123',
     });
     jest.resetAllMocks();
-    httpMock.setup();
   });
 
   afterEach(() => {
     hostRules.clear();
-    httpMock.reset();
     delete process.env.RENOVATE_EXPERIMENTAL_NO_MAVEN_POM_CHECK;
   });
 
diff --git a/lib/datasource/crate/index.spec.ts b/lib/datasource/crate/index.spec.ts
index 00ae5986f2c7cb88cdf73a4d559190c9d94bb695..b62822b12eb36b98ddc499857d273ee3740eb674 100644
--- a/lib/datasource/crate/index.spec.ts
+++ b/lib/datasource/crate/index.spec.ts
@@ -78,8 +78,6 @@ describe(getName(), () => {
     let adminConfig: RepoAdminConfig;
 
     beforeEach(async () => {
-      httpMock.setup();
-
       tmpDir = await dir();
 
       adminConfig = {
@@ -96,8 +94,6 @@ describe(getName(), () => {
       fs.rmdirSync(tmpDir.path, { recursive: true });
       tmpDir = null;
       setAdminConfig();
-
-      httpMock.reset();
     });
 
     it('returns null for missing registry url', async () => {
diff --git a/lib/datasource/dart/index.spec.ts b/lib/datasource/dart/index.spec.ts
index 0d14f99c40f268933649f5e74e8117b59cd64ca7..286ac8767dd682eb2b227670979c03abd9107885 100644
--- a/lib/datasource/dart/index.spec.ts
+++ b/lib/datasource/dart/index.spec.ts
@@ -8,14 +8,6 @@ const body = loadJsonFixture('shared_preferences.json');
 const baseUrl = 'https://pub.dartlang.org/api/packages/';
 
 describe(getName(), () => {
-  beforeEach(() => {
-    httpMock.setup();
-  });
-
-  afterEach(() => {
-    httpMock.reset();
-  });
-
   describe('getReleases', () => {
     it('returns null for empty result', async () => {
       httpMock.scope(baseUrl).get('/non_sense').reply(200, null);
diff --git a/lib/datasource/datasource.spec.ts b/lib/datasource/datasource.spec.ts
index 1df40a4d1e9fb8d2a9f18a4af3d148ed7c2581e2..6a1255ff2800de354651aea022f137fae5ebc6c7 100644
--- a/lib/datasource/datasource.spec.ts
+++ b/lib/datasource/datasource.spec.ts
@@ -24,14 +24,6 @@ class TestDatasource extends Datasource {
 }
 
 describe(getName(), () => {
-  beforeEach(() => {
-    httpMock.setup();
-  });
-
-  afterEach(() => {
-    httpMock.reset();
-  });
-
   it('should throw on 429', async () => {
     const testDatasource = new TestDatasource();
 
diff --git a/lib/datasource/docker/common.spec.ts b/lib/datasource/docker/common.spec.ts
index 84f07292090f1a5ccb548050a06d013c931be062..7bc9b260cae97be6b068eb039c4aef643500961d 100644
--- a/lib/datasource/docker/common.spec.ts
+++ b/lib/datasource/docker/common.spec.ts
@@ -1,4 +1,3 @@
-import * as httpMock from '../../../test/http-mock';
 import { getName, mocked } from '../../../test/util';
 import * as _hostRules from '../../util/host-rules';
 import * as dockerCommon from './common';
@@ -10,7 +9,6 @@ jest.mock('../../util/host-rules');
 
 describe(getName(), () => {
   beforeEach(() => {
-    httpMock.setup();
     hostRules.find.mockReturnValue({
       username: 'some-username',
       password: 'some-password',
@@ -20,7 +18,6 @@ describe(getName(), () => {
 
   afterEach(() => {
     jest.resetAllMocks();
-    httpMock.reset();
   });
 
   describe('getRegistryRepository', () => {
diff --git a/lib/datasource/docker/index.spec.ts b/lib/datasource/docker/index.spec.ts
index 2b82f076385743cae4637b527edbcddf9d1720a3..99b397c594be8bf87a024013f0ae2519ce945468 100644
--- a/lib/datasource/docker/index.spec.ts
+++ b/lib/datasource/docker/index.spec.ts
@@ -44,7 +44,6 @@ function mockEcrAuthReject(msg: string) {
 
 describe(getName(), () => {
   beforeEach(() => {
-    httpMock.setup();
     hostRules.find.mockReturnValue({
       username: 'some-username',
       password: 'some-password',
@@ -54,7 +53,6 @@ describe(getName(), () => {
 
   afterEach(() => {
     jest.resetAllMocks();
-    httpMock.reset();
   });
 
   describe('getDigest', () => {
diff --git a/lib/datasource/galaxy-collection/index.spec.ts b/lib/datasource/galaxy-collection/index.spec.ts
index 8a5725cb1dbd80afe5eb5a4febc52bab0ebef3d1..4844b6c5ff67488b5eb084761051fe3c53e5a91e 100644
--- a/lib/datasource/galaxy-collection/index.spec.ts
+++ b/lib/datasource/galaxy-collection/index.spec.ts
@@ -22,14 +22,6 @@ const baseUrl = 'https://galaxy.ansible.com';
 
 describe(getName(), () => {
   describe('getReleases', () => {
-    beforeEach(() => {
-      httpMock.setup();
-    });
-
-    afterEach(() => {
-      httpMock.reset();
-    });
-
     it('returns null for 404 result', async () => {
       httpMock.scope(baseUrl).get('/api/v2/collections/foo/bar/').reply(404);
       expect(
diff --git a/lib/datasource/galaxy/index.spec.ts b/lib/datasource/galaxy/index.spec.ts
index c4b16844a45f5633c8ee9d4c00c2f9b994c3944c..56eddd6ba3b2714364166ae986bc1e4aabdac329 100644
--- a/lib/datasource/galaxy/index.spec.ts
+++ b/lib/datasource/galaxy/index.spec.ts
@@ -11,14 +11,6 @@ const baseUrl = 'https://galaxy.ansible.com/';
 
 describe(getName(), () => {
   describe('getReleases', () => {
-    beforeEach(() => {
-      httpMock.setup();
-    });
-
-    afterEach(() => {
-      httpMock.reset();
-    });
-
     it('returns null for empty result', async () => {
       httpMock
         .scope(baseUrl)
diff --git a/lib/datasource/github-releases/index.spec.ts b/lib/datasource/github-releases/index.spec.ts
index 4bf1e18110c932143623432f9c1ab351b7257dc3..35ff90fbc92cd491704039db237c3dc9dd5ab7b0 100644
--- a/lib/datasource/github-releases/index.spec.ts
+++ b/lib/datasource/github-releases/index.spec.ts
@@ -29,11 +29,6 @@ describe(getName(), () => {
     hostRules.find.mockReturnValue({
       token: 'some-token',
     });
-    httpMock.setup();
-  });
-
-  afterEach(() => {
-    httpMock.reset();
   });
 
   describe('getReleases', () => {
diff --git a/lib/datasource/github-tags/index.spec.ts b/lib/datasource/github-tags/index.spec.ts
index cd038f8f6c51bf7288b9dfa319822e92a3822437..26ad50fa7ad22b2a6726ebdb5766e5b0949840fc 100644
--- a/lib/datasource/github-tags/index.spec.ts
+++ b/lib/datasource/github-tags/index.spec.ts
@@ -12,17 +12,12 @@ const githubEnterpriseApiHost = 'https://git.enterprise.com';
 
 describe(getName(), () => {
   beforeEach(() => {
-    httpMock.reset();
-    httpMock.setup();
     jest.resetAllMocks();
     hostRules.hosts = jest.fn(() => []);
     hostRules.find.mockReturnValue({
       token: 'some-token',
     });
   });
-  afterEach(() => {
-    httpMock.reset();
-  });
 
   describe('getDigest', () => {
     const lookupName = 'some/dep';
@@ -110,17 +105,12 @@ describe(getName(), () => {
   });
   describe('getReleases', () => {
     beforeEach(() => {
-      httpMock.reset();
-      httpMock.setup();
       jest.resetAllMocks();
       hostRules.hosts = jest.fn(() => []);
       hostRules.find.mockReturnValue({
         token: 'some-token',
       });
     });
-    afterEach(() => {
-      httpMock.reset();
-    });
 
     const depName = 'some/dep2';
 
diff --git a/lib/datasource/gitlab-tags/index.spec.ts b/lib/datasource/gitlab-tags/index.spec.ts
index 1b106f37faa7343c84c8ffeac0a8f264fcf9ded8..c451a6a8b8abdb94dca16c774d5748564316b06b 100644
--- a/lib/datasource/gitlab-tags/index.spec.ts
+++ b/lib/datasource/gitlab-tags/index.spec.ts
@@ -4,13 +4,6 @@ import { getName } from '../../../test/util';
 import { id as datasource } from '.';
 
 describe(getName(), () => {
-  beforeEach(() => {
-    httpMock.reset();
-    httpMock.setup();
-  });
-  afterEach(() => {
-    httpMock.reset();
-  });
   describe('getReleases', () => {
     it('returns tags from custom registry', async () => {
       const body = [
diff --git a/lib/datasource/go/index.spec.ts b/lib/datasource/go/index.spec.ts
index 0be03b9737deb27651294f42525c007428568328..d5c4ea059a00a6b21c354183648418989b570838 100644
--- a/lib/datasource/go/index.spec.ts
+++ b/lib/datasource/go/index.spec.ts
@@ -48,13 +48,11 @@ const resGitHubEnterprise = `<!DOCTYPE html>
 
 describe(getName(), () => {
   beforeEach(() => {
-    httpMock.setup();
     hostRules.find.mockReturnValue({});
     hostRules.hosts.mockReturnValue([]);
   });
 
   afterEach(() => {
-    httpMock.reset();
     jest.resetAllMocks();
   });
 
@@ -374,7 +372,6 @@ describe(getName(), () => {
       const tags = [{ name: 'a/v1.0.0' }, { name: 'b/v2.0.0' }];
 
       for (const pkg of packages) {
-        httpMock.setup();
         httpMock
           .scope('https://api.github.com/')
           .get('/repos/x/text/tags?per_page=100')
@@ -389,7 +386,7 @@ describe(getName(), () => {
 
         const httpCalls = httpMock.getTrace();
         expect(httpCalls).toMatchSnapshot();
-        httpMock.reset();
+        httpMock.clear();
       }
     });
     it('returns none if no tags match submodules', async () => {
@@ -400,7 +397,6 @@ describe(getName(), () => {
       const tags = [{ name: 'v1.0.0' }, { name: 'v2.0.0' }];
 
       for (const pkg of packages) {
-        httpMock.setup();
         httpMock
           .scope('https://api.github.com/')
           .get('/repos/x/text/tags?per_page=100')
@@ -413,7 +409,7 @@ describe(getName(), () => {
 
         const httpCalls = httpMock.getTrace();
         expect(httpCalls).toMatchSnapshot();
-        httpMock.reset();
+        httpMock.clear();
       }
     });
     it('works for nested modules on github v2+ major upgrades', async () => {
diff --git a/lib/datasource/gradle-version/index.spec.ts b/lib/datasource/gradle-version/index.spec.ts
index 078303f6e647b158541f48ee9a6d0c19353f5b38..a46f1f55520cadb47050a4e32457179edac3a5ab 100644
--- a/lib/datasource/gradle-version/index.spec.ts
+++ b/lib/datasource/gradle-version/index.spec.ts
@@ -18,11 +18,6 @@ describe(getName(), () => {
         depName: 'abc',
       };
       jest.clearAllMocks();
-      httpMock.setup();
-    });
-
-    afterEach(() => {
-      httpMock.reset();
     });
 
     it('processes real data', async () => {
diff --git a/lib/datasource/helm/index.spec.ts b/lib/datasource/helm/index.spec.ts
index ff3a14ed97537fa9aaaebecadaeafb4f51af83aa..d4ed9bb425b5d3c6c6bc3eb88132177efe29f9cf 100644
--- a/lib/datasource/helm/index.spec.ts
+++ b/lib/datasource/helm/index.spec.ts
@@ -10,11 +10,6 @@ describe(getName(), () => {
   describe('getReleases', () => {
     beforeEach(() => {
       jest.resetAllMocks();
-      httpMock.setup();
-    });
-
-    afterEach(() => {
-      httpMock.reset();
     });
 
     it('returns null if lookupName was not provided', async () => {
diff --git a/lib/datasource/hex/index.spec.ts b/lib/datasource/hex/index.spec.ts
index 739be18d1e017a42434ae1ee101f5f85635bbbe9..d6f453018a816a11c511845b7bb85899d395b2f7 100644
--- a/lib/datasource/hex/index.spec.ts
+++ b/lib/datasource/hex/index.spec.ts
@@ -17,12 +17,10 @@ describe(getName(), () => {
   beforeEach(() => {
     hostRules.hosts.mockReturnValue([]);
     hostRules.find.mockReturnValue({});
-    httpMock.setup();
   });
 
   afterEach(() => {
     jest.resetAllMocks();
-    httpMock.reset();
   });
 
   describe('getReleases', () => {
diff --git a/lib/datasource/jenkins-plugins/index.spec.ts b/lib/datasource/jenkins-plugins/index.spec.ts
index 0b7fa723353bad1256879dd260ed15e794943532..8a2e7eb9a69c5453eaf4db4906dd1a54a2eb3b9b 100644
--- a/lib/datasource/jenkins-plugins/index.spec.ts
+++ b/lib/datasource/jenkins-plugins/index.spec.ts
@@ -21,7 +21,6 @@ describe(getName(), () => {
 
     beforeEach(() => {
       resetCache();
-      httpMock.setup();
       process.env.RENOVATE_SKIP_CACHE = 'true';
       jest.resetAllMocks();
     });
@@ -30,7 +29,6 @@ describe(getName(), () => {
       if (!httpMock.allUsed()) {
         throw new Error('Not all http mocks have been used!');
       }
-      httpMock.reset();
       process.env.RENOVATE_SKIP_CACHE = SKIP_CACHE;
     });
 
diff --git a/lib/datasource/maven/index.spec.ts b/lib/datasource/maven/index.spec.ts
index 868de5c27db68256d7dd3cd01798bb18171bcd36..ca72d31f4f64e79b8747578595129d29df3549fa 100644
--- a/lib/datasource/maven/index.spec.ts
+++ b/lib/datasource/maven/index.spec.ts
@@ -86,12 +86,10 @@ describe(getName(), () => {
       token: 'abc123',
     });
     jest.resetAllMocks();
-    httpMock.setup();
   });
 
   afterEach(() => {
     hostRules.clear();
-    httpMock.reset();
     delete process.env.RENOVATE_EXPERIMENTAL_NO_MAVEN_POM_CHECK;
   });
 
diff --git a/lib/datasource/npm/get.spec.ts b/lib/datasource/npm/get.spec.ts
index 0c444d8800bf5fe96d153869e89b0102a587472d..649498bfef7705727d5a5293dd552e0a23570efd 100644
--- a/lib/datasource/npm/get.spec.ts
+++ b/lib/datasource/npm/get.spec.ts
@@ -15,14 +15,9 @@ describe(getName(), () => {
   beforeEach(() => {
     jest.clearAllMocks();
     resetMemCache();
-    httpMock.setup();
     hostRules.clear();
   });
 
-  afterEach(() => {
-    httpMock.reset();
-  });
-
   describe('has bearer auth', () => {
     const configs = [
       `registry=https://test.org\n//test.org/:_authToken=XXX`,
diff --git a/lib/datasource/npm/index.spec.ts b/lib/datasource/npm/index.spec.ts
index 6e98e2b28d1d909ed016d18e5c1be9484044b435..b81d2b79c13e8b3ad8503711bbd8ef766260f873 100644
--- a/lib/datasource/npm/index.spec.ts
+++ b/lib/datasource/npm/index.spec.ts
@@ -18,7 +18,6 @@ let npmResponse: any;
 describe(getName(), () => {
   beforeEach(() => {
     jest.resetAllMocks();
-    httpMock.setup();
     setAdminConfig();
     hostRules.clear();
     resetCache();
@@ -52,7 +51,6 @@ describe(getName(), () => {
   afterEach(() => {
     delete process.env.RENOVATE_CACHE_NPM_MINUTES;
     mockDate.reset();
-    httpMock.reset();
   });
 
   it('should return null for no versions', async () => {
diff --git a/lib/datasource/nuget/index.spec.ts b/lib/datasource/nuget/index.spec.ts
index 3ed42025a9a9617e6341b4886505fbc0fe65675b..61091a9ccc5d06c127f1cc95e954028ccb29d9c9 100644
--- a/lib/datasource/nuget/index.spec.ts
+++ b/lib/datasource/nuget/index.spec.ts
@@ -134,11 +134,6 @@ describe(getName(), () => {
       jest.resetAllMocks();
       hostRules.hosts.mockReturnValue([]);
       hostRules.find.mockReturnValue({});
-      httpMock.setup();
-    });
-
-    afterEach(() => {
-      httpMock.reset();
     });
 
     it(`can't detect nuget feed version`, async () => {
diff --git a/lib/datasource/orb/index.spec.ts b/lib/datasource/orb/index.spec.ts
index 590ba37c9a2f9df6e75ac959caee0d31067e63e4..b3d3940b3e98faf216836c1a3200781b78a8792a 100644
--- a/lib/datasource/orb/index.spec.ts
+++ b/lib/datasource/orb/index.spec.ts
@@ -30,11 +30,6 @@ describe(getName(), () => {
   describe('getReleases', () => {
     beforeEach(() => {
       jest.clearAllMocks();
-      httpMock.setup();
-    });
-
-    afterEach(() => {
-      httpMock.reset();
     });
 
     it('returns null for empty result', async () => {
diff --git a/lib/datasource/packagist/index.spec.ts b/lib/datasource/packagist/index.spec.ts
index b0fc54e79ad32587bd9ce00cee480a41ace9bfae..4e7e13b990b7da55fe718eddfa26754d6095ccf6 100644
--- a/lib/datasource/packagist/index.spec.ts
+++ b/lib/datasource/packagist/index.spec.ts
@@ -21,7 +21,6 @@ describe(getName(), () => {
     let config: any;
     beforeEach(() => {
       jest.resetAllMocks();
-      httpMock.setup();
       hostRules.find = jest.fn((input) => input);
       hostRules.hosts = jest.fn(() => []);
       config = {
@@ -33,10 +32,6 @@ describe(getName(), () => {
       };
     });
 
-    afterEach(() => {
-      httpMock.reset();
-    });
-
     it('supports custom registries', async () => {
       config = {
         registryUrls: ['https://composer.renovatebot.com'],
diff --git a/lib/datasource/pod/index.spec.ts b/lib/datasource/pod/index.spec.ts
index d5a215b15cad2b911b58420c322a46ea03f12ab7..66db34635dfcf591fdf4f3a939f0a829f5dbddb7 100644
--- a/lib/datasource/pod/index.spec.ts
+++ b/lib/datasource/pod/index.spec.ts
@@ -19,11 +19,6 @@ describe(getName(), () => {
   describe('getReleases', () => {
     beforeEach(() => {
       jest.resetAllMocks();
-      httpMock.setup();
-    });
-
-    afterEach(() => {
-      httpMock.reset();
     });
 
     it('returns null for invalid inputs', async () => {
diff --git a/lib/datasource/pypi/index.spec.ts b/lib/datasource/pypi/index.spec.ts
index 880faa3bb05adc7e464607abd9344410aae56a58..c635b07517a9e8392ca9f5f068cde2245b5db053 100644
--- a/lib/datasource/pypi/index.spec.ts
+++ b/lib/datasource/pypi/index.spec.ts
@@ -22,13 +22,11 @@ describe(getName(), () => {
     beforeEach(() => {
       process.env = { ...OLD_ENV };
       delete process.env.PIP_INDEX_URL;
-      httpMock.setup();
       jest.resetAllMocks();
     });
 
     afterEach(() => {
       process.env = OLD_ENV;
-      httpMock.reset();
     });
 
     it('returns null for empty result', async () => {
diff --git a/lib/datasource/repology/index.spec.ts b/lib/datasource/repology/index.spec.ts
index 3e61a3675ed0eaa1811354a2daf03a52d6726084..f984ac7bd8070c47d9cc465f91378b98f009a663 100644
--- a/lib/datasource/repology/index.spec.ts
+++ b/lib/datasource/repology/index.spec.ts
@@ -54,12 +54,6 @@ const fixtureJdk = loadFixture(`openjdk.json`);
 
 describe(getName(), () => {
   describe('getReleases', () => {
-    beforeEach(() => {
-      httpMock.setup();
-    });
-
-    afterEach(() => httpMock.reset());
-
     it('returns null for empty result', async () => {
       mockResolverCall('debian_stable', 'nginx', 'binname', {
         status: 200,
diff --git a/lib/datasource/ruby-version/index.spec.ts b/lib/datasource/ruby-version/index.spec.ts
index d227fc8bf3936359333b56b54c766f9813046062..3efbd83d385eef60c8e986c089573f8b133ff21b 100644
--- a/lib/datasource/ruby-version/index.spec.ts
+++ b/lib/datasource/ruby-version/index.spec.ts
@@ -7,14 +7,6 @@ const rubyReleasesHtml = loadFixture('releases.html');
 
 describe(getName(), () => {
   describe('getReleases', () => {
-    beforeEach(() => {
-      httpMock.setup();
-    });
-
-    afterEach(() => {
-      httpMock.reset();
-    });
-
     it('parses real data', async () => {
       httpMock
         .scope('https://www.ruby-lang.org')
diff --git a/lib/datasource/rubygems/index.spec.ts b/lib/datasource/rubygems/index.spec.ts
index dce97126fb72f27f0c2afea8f9f4511fa1a2b8a3..83a07492d79242680eba26d0d6408eeaa5480b51 100644
--- a/lib/datasource/rubygems/index.spec.ts
+++ b/lib/datasource/rubygems/index.spec.ts
@@ -25,13 +25,11 @@ describe(getName(), () => {
 
     beforeEach(() => {
       resetCache();
-      httpMock.setup();
       process.env.RENOVATE_SKIP_CACHE = 'true';
       jest.resetAllMocks();
     });
 
     afterEach(() => {
-      httpMock.reset();
       process.env.RENOVATE_SKIP_CACHE = SKIP_CACHE;
     });
 
diff --git a/lib/datasource/terraform-module/index.spec.ts b/lib/datasource/terraform-module/index.spec.ts
index 224749e1b7920a6d4971308172e97056d1255552..d93b9a67da4f43ac5333bcf70e3027bd8e4d466a 100644
--- a/lib/datasource/terraform-module/index.spec.ts
+++ b/lib/datasource/terraform-module/index.spec.ts
@@ -16,11 +16,6 @@ describe(getName(), () => {
   describe('getReleases', () => {
     beforeEach(() => {
       jest.clearAllMocks();
-      httpMock.setup();
-    });
-
-    afterEach(() => {
-      httpMock.reset();
     });
 
     it('returns null for empty result', async () => {
diff --git a/lib/datasource/terraform-provider/__snapshots__/index.spec.ts.snap b/lib/datasource/terraform-provider/__snapshots__/index.spec.ts.snap
index 600ed430ee6c808857790d24207ccabc7a8e13ad..0f5172b44cea823ea6333fdf0171fab900fd2997 100644
--- a/lib/datasource/terraform-provider/__snapshots__/index.spec.ts.snap
+++ b/lib/datasource/terraform-provider/__snapshots__/index.spec.ts.snap
@@ -646,3 +646,38 @@ Array [
 `;
 
 exports[`datasource/terraform-provider/index getReleases simulate failing secondary release source 1`] = `null`;
+
+exports[`datasource/terraform-provider/index getReleases simulate failing secondary release source 2`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "host": "registry.terraform.io",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.terraform.io/.well-known/terraform.json",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "host": "registry.terraform.io",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.terraform.io/v1/providers/hashicorp/datadog",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "host": "releases.hashicorp.com",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://releases.hashicorp.com/index.json",
+  },
+]
+`;
diff --git a/lib/datasource/terraform-provider/index.spec.ts b/lib/datasource/terraform-provider/index.spec.ts
index 10a5abb85e8c55a453e4f0d65ca874dd1ac5ed90..10751814ae0e593dc2ab8babe0fe2948a2233f34 100644
--- a/lib/datasource/terraform-provider/index.spec.ts
+++ b/lib/datasource/terraform-provider/index.spec.ts
@@ -14,11 +14,6 @@ describe(getName(), () => {
   describe('getReleases', () => {
     beforeEach(() => {
       jest.clearAllMocks();
-      httpMock.setup();
-    });
-
-    afterEach(() => {
-      httpMock.reset();
     });
 
     it('returns null for empty result', async () => {
@@ -127,7 +122,7 @@ describe(getName(), () => {
     it('simulate failing secondary release source', async () => {
       httpMock
         .scope(primaryUrl)
-        .get('/v1/providers/hashicorp/google-beta')
+        .get('/v1/providers/hashicorp/datadog')
         .reply(404, {
           errors: ['Not Found'],
         })
@@ -141,6 +136,7 @@ describe(getName(), () => {
       });
       expect(res).toMatchSnapshot();
       expect(res).toBeNull();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('returns null for error in service discovery', async () => {
       httpMock.scope(primaryUrl).get('/.well-known/terraform.json').reply(404);
diff --git a/lib/logger/err-serializer.spec.ts b/lib/logger/err-serializer.spec.ts
index afb2d1d65d8ba1f3b4492724cc24ee5f10714b92..7864faff5135ca757f071e023f40d15f96efbf49 100644
--- a/lib/logger/err-serializer.spec.ts
+++ b/lib/logger/err-serializer.spec.ts
@@ -38,7 +38,6 @@ describe(getName(), () => {
     beforeEach(() => {
       // reset module
       jest.resetAllMocks();
-      httpMock.setup();
       // clean up hostRules
       hostRules.clear();
       hostRules.add({
@@ -47,7 +46,6 @@ describe(getName(), () => {
         token: 'token',
       });
     });
-    afterEach(() => httpMock.reset());
 
     it('handles http error', async () => {
       httpMock
diff --git a/lib/manager/batect-wrapper/artifacts.spec.ts b/lib/manager/batect-wrapper/artifacts.spec.ts
index 1d14f7b76fd1aacf368758e98e4fb53f03b70ab7..94407ba1862cb4593626029c965d25436f37c1ac 100644
--- a/lib/manager/batect-wrapper/artifacts.spec.ts
+++ b/lib/manager/batect-wrapper/artifacts.spec.ts
@@ -23,8 +23,6 @@ function artifactForPath(
 
 describe(getName(), () => {
   beforeEach(() => {
-    httpMock.setup();
-
     httpMock
       .scope('https://github.com')
       .get('/batect/batect/releases/download/1.2.3/batect')
@@ -46,9 +44,8 @@ describe(getName(), () => {
       .reply(418);
   });
 
-  afterEach(() => {
-    httpMock.reset();
-  });
+  // TODO: fix mocks
+  afterEach(() => httpMock.clear(false));
 
   describe('updateArtifacts', () => {
     it('returns updated files if the wrapper script is in the root directory', async () => {
diff --git a/lib/manager/bazel/update.spec.ts b/lib/manager/bazel/update.spec.ts
index 368c092205f3255c38416beb8251bf9cc4e6bbac..3be8723119eef1616a846b125910dd5f1e1331fc 100644
--- a/lib/manager/bazel/update.spec.ts
+++ b/lib/manager/bazel/update.spec.ts
@@ -20,11 +20,6 @@ describe(getName(), () => {
   describe('updateDependency', () => {
     beforeEach(() => {
       jest.resetAllMocks();
-      httpMock.setup();
-    });
-
-    afterEach(() => {
-      httpMock.reset();
     });
 
     it('updates tag', async () => {
diff --git a/lib/manager/gradle-wrapper/artifacts-real.spec.ts b/lib/manager/gradle-wrapper/artifacts-real.spec.ts
index 3df946849148e16742aa2e485731e48795dab03f..181a33286987ef9f5357906d97c9e47cbdcfb0fc 100644
--- a/lib/manager/gradle-wrapper/artifacts-real.spec.ts
+++ b/lib/manager/gradle-wrapper/artifacts-real.spec.ts
@@ -45,12 +45,10 @@ describe(getName(), () => {
       jest.resetAllMocks();
       await setExecConfig(adminConfig as never);
       setAdminConfig(adminConfig);
-      httpMock.setup();
     });
 
     afterEach(async () => {
       await Git(fixtures).checkout(['HEAD', '--', '.']);
-      httpMock.reset();
       setAdminConfig();
     });
 
diff --git a/lib/manager/gradle-wrapper/artifacts.spec.ts b/lib/manager/gradle-wrapper/artifacts.spec.ts
index 16f92f1dd04732d6a7243b077eabf6e897a7fc9c..ba06ec203e424dd127865c70b2f40a1b669cd3f2 100644
--- a/lib/manager/gradle-wrapper/artifacts.spec.ts
+++ b/lib/manager/gradle-wrapper/artifacts.spec.ts
@@ -49,7 +49,6 @@ function readString(...paths: string[]): Promise<string> {
 describe(getName(), () => {
   beforeEach(async () => {
     jest.resetAllMocks();
-    httpMock.setup();
 
     env.getChildProcessEnv.mockReturnValue({
       ...envMock.basic,
@@ -65,7 +64,6 @@ describe(getName(), () => {
   });
 
   afterEach(() => {
-    httpMock.reset();
     setAdminConfig();
   });
 
diff --git a/lib/manager/homebrew/update.spec.ts b/lib/manager/homebrew/update.spec.ts
index 1ffe47fabcafb429787af405cab02598dcd3eff6..44b6618413cd7f161eb9a96d20265c730550ffff 100644
--- a/lib/manager/homebrew/update.spec.ts
+++ b/lib/manager/homebrew/update.spec.ts
@@ -12,11 +12,6 @@ describe(getName(), () => {
   beforeEach(() => {
     jest.resetAllMocks();
     jest.resetModules();
-    httpMock.setup();
-  });
-
-  afterEach(() => {
-    httpMock.reset();
   });
 
   it('updates "releases" github dependency', async () => {
diff --git a/lib/manager/npm/update/locked-dependency/__snapshots__/index.spec.ts.snap b/lib/manager/npm/update/locked-dependency/__snapshots__/index.spec.ts.snap
new file mode 100644
index 0000000000000000000000000000000000000000..3f56c989b58cb3d7c801d1ca4c1a41fce1ca079d
--- /dev/null
+++ b/lib/manager/npm/update/locked-dependency/__snapshots__/index.spec.ts.snap
@@ -0,0 +1,46 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`manager/npm/update/locked-dependency/index updateLockedDependency() remediates mime 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "host": "registry.npmjs.org",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.npmjs.org/mime",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "host": "registry.npmjs.org",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.npmjs.org/send",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "host": "registry.npmjs.org",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.npmjs.org/type-is",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "host": "registry.npmjs.org",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.npmjs.org/serve-static",
+  },
+]
+`;
diff --git a/lib/manager/npm/update/locked-dependency/__snapshots__/parent-version.spec.ts.snap b/lib/manager/npm/update/locked-dependency/__snapshots__/parent-version.spec.ts.snap
new file mode 100644
index 0000000000000000000000000000000000000000..02a90909a0a3df66a084947b0ad8796a34084402
--- /dev/null
+++ b/lib/manager/npm/update/locked-dependency/__snapshots__/parent-version.spec.ts.snap
@@ -0,0 +1,86 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`manager/npm/update/locked-dependency/parent-version getLockedDependencies() finds indirect dependency 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "host": "registry.npmjs.org",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.npmjs.org/send",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "host": "registry.npmjs.org",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.npmjs.org/express",
+  },
+]
+`;
+
+exports[`manager/npm/update/locked-dependency/parent-version getLockedDependencies() finds removed dependencies 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "host": "registry.npmjs.org",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.npmjs.org/buffer-crc32",
+  },
+]
+`;
+
+exports[`manager/npm/update/locked-dependency/parent-version getLockedDependencies() finds when a greater version is needed 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "host": "registry.npmjs.org",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.npmjs.org/qs",
+  },
+]
+`;
+
+exports[`manager/npm/update/locked-dependency/parent-version getLockedDependencies() finds when a range matches greater versions 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "host": "registry.npmjs.org",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.npmjs.org/type-is",
+  },
+]
+`;
+
+exports[`manager/npm/update/locked-dependency/parent-version getLockedDependencies() returns null if no matching 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "host": "registry.npmjs.org",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.npmjs.org/debug",
+  },
+]
+`;
diff --git a/lib/manager/npm/update/locked-dependency/index.spec.ts b/lib/manager/npm/update/locked-dependency/index.spec.ts
index 8b63d485f0b30c41ca5a03204683123f949bfb92..36a688f6ab1a9a507fcab91f136f17f39b33009f 100644
--- a/lib/manager/npm/update/locked-dependency/index.spec.ts
+++ b/lib/manager/npm/update/locked-dependency/index.spec.ts
@@ -17,7 +17,6 @@ describe(getName(), () => {
   describe('updateLockedDependency()', () => {
     let config: UpdateLockedConfig;
     beforeEach(() => {
-      httpMock.setup();
       config = {
         packageFile: 'package.json',
         packageFileContent,
@@ -28,9 +27,7 @@ describe(getName(), () => {
         newVersion: '1.0.1',
       };
     });
-    afterEach(() => {
-      httpMock.reset();
-    });
+
     it('validates filename', async () => {
       expect(
         await updateLockedDependency({ ...config, lockFile: 'yarn.lock' })
@@ -114,14 +111,6 @@ describe(getName(), () => {
       config.depName = 'mime';
       config.currentVersion = '1.2.11';
       config.newVersion = '1.4.1';
-      httpMock
-        .scope('https://registry.npmjs.org')
-        .get('/accepts')
-        .reply(200, acceptsJson);
-      httpMock
-        .scope('https://registry.npmjs.org')
-        .get('/express')
-        .reply(200, expressJson);
       httpMock
         .scope('https://registry.npmjs.org')
         .get('/mime')
@@ -142,6 +131,7 @@ describe(getName(), () => {
       const packageLock = JSON.parse(res['package-lock.json']);
       expect(packageLock.dependencies.mime.version).toEqual('1.4.1');
       expect(packageLock.dependencies.express.version).toEqual('4.16.0');
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
 });
diff --git a/lib/manager/npm/update/locked-dependency/parent-version.spec.ts b/lib/manager/npm/update/locked-dependency/parent-version.spec.ts
index 0415965d1b324eb85c3378745b637d2cad8baa33..5e9801319376cda41c366694307e4f11557f7034 100644
--- a/lib/manager/npm/update/locked-dependency/parent-version.spec.ts
+++ b/lib/manager/npm/update/locked-dependency/parent-version.spec.ts
@@ -6,13 +6,6 @@ const expressJson = loadJsonFixture('express.json');
 
 describe(getName(), () => {
   describe('getLockedDependencies()', () => {
-    beforeEach(() => {
-      httpMock.setup();
-    });
-
-    afterEach(() => {
-      httpMock.reset();
-    });
     it('finds indirect dependency', async () => {
       httpMock
         .scope('https://registry.npmjs.org')
@@ -32,10 +25,13 @@ describe(getName(), () => {
         .scope('https://registry.npmjs.org')
         .get('/express')
         .reply(200, expressJson);
+
       expect(
         await findFirstParentVersion('express', '4.0.0', 'send', '0.11.1')
       ).toEqual('4.11.1');
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
+
     it('finds removed dependencies', async () => {
       httpMock
         .scope('https://registry.npmjs.org')
@@ -48,10 +44,7 @@ describe(getName(), () => {
           },
           'dist-tags': { latest: '10.0.0' },
         });
-      httpMock
-        .scope('https://registry.npmjs.org')
-        .get('/express')
-        .reply(200, expressJson);
+
       expect(
         await findFirstParentVersion(
           'express',
@@ -60,7 +53,9 @@ describe(getName(), () => {
           '10.0.0'
         )
       ).toEqual('4.9.1');
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
+
     it('finds when a greater version is needed', async () => {
       httpMock
         .scope('https://registry.npmjs.org')
@@ -75,14 +70,13 @@ describe(getName(), () => {
           },
           'dist-tags': { latest: '6.2.0' },
         });
-      httpMock
-        .scope('https://registry.npmjs.org')
-        .get('/express')
-        .reply(200, expressJson);
+
       expect(
         await findFirstParentVersion('express', '4.0.0', 'qs', '6.0.4')
       ).toEqual('4.14.0');
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
+
     it('finds when a range matches greater versions', async () => {
       httpMock
         .scope('https://registry.npmjs.org')
@@ -96,14 +90,13 @@ describe(getName(), () => {
           },
           'dist-tags': { latest: '1.6.15' },
         });
-      httpMock
-        .scope('https://registry.npmjs.org')
-        .get('/express')
-        .reply(200, expressJson);
+
       expect(
         await findFirstParentVersion('express', '4.16.1', 'type-is', '1.2.1')
       ).toEqual('4.16.1');
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
+
     it('returns null if no matching', async () => {
       httpMock
         .scope('https://registry.npmjs.org')
@@ -116,13 +109,11 @@ describe(getName(), () => {
           },
           'dist-tags': { latest: '10.0.0' },
         });
-      httpMock
-        .scope('https://registry.npmjs.org')
-        .get('/express')
-        .reply(200, expressJson);
+
       expect(
         await findFirstParentVersion('express', '4.16.1', 'debug', '9.0.0')
       ).toBeNull();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
 });
diff --git a/lib/platform/bitbucket-server/index.spec.ts b/lib/platform/bitbucket-server/index.spec.ts
index 45d6d558ff97fbd8bb1ea1d516a19a5acd0b0712..1d5ce519010527079a8c5236a4c53c6ce0c1d4da 100644
--- a/lib/platform/bitbucket-server/index.spec.ts
+++ b/lib/platform/bitbucket-server/index.spec.ts
@@ -203,8 +203,6 @@ describe(getName(), () => {
       beforeEach(async () => {
         // reset module
         jest.resetModules();
-        httpMock.reset();
-        httpMock.setup();
         jest.mock('delay');
         jest.mock('../../util/git');
         jest.mock('../../util/host-rules');
@@ -230,9 +228,6 @@ describe(getName(), () => {
           password,
         });
       });
-      afterEach(() => {
-        httpMock.reset();
-      });
 
       describe('initPlatform()', () => {
         it('should throw if no endpoint', () => {
diff --git a/lib/platform/bitbucket/comments.spec.ts b/lib/platform/bitbucket/comments.spec.ts
index 2556bdbd84feb7c879f41e8291d9fa076a2687ff..aebc255bb7f5022151a109ce5fd657ee7010b323 100644
--- a/lib/platform/bitbucket/comments.spec.ts
+++ b/lib/platform/bitbucket/comments.spec.ts
@@ -11,14 +11,8 @@ describe(getName(), () => {
   beforeEach(() => {
     jest.clearAllMocks();
 
-    httpMock.reset();
-    httpMock.setup();
-
     setBaseUrl(baseUrl);
   });
-  afterEach(() => {
-    httpMock.reset();
-  });
 
   describe('ensureComment()', () => {
     it('does not throw', async () => {
diff --git a/lib/platform/bitbucket/index.spec.ts b/lib/platform/bitbucket/index.spec.ts
index d0247622756d6816a5314b981e734d747e756341..29be605d924f8502e00f382b01d8139c118d24ff 100644
--- a/lib/platform/bitbucket/index.spec.ts
+++ b/lib/platform/bitbucket/index.spec.ts
@@ -43,8 +43,6 @@ describe(getName(), () => {
   beforeEach(async () => {
     // reset module
     jest.resetModules();
-    httpMock.reset();
-    httpMock.setup();
     jest.mock('../../util/git');
     jest.mock('../../util/host-rules');
     jest.mock('../../logger');
@@ -63,9 +61,6 @@ describe(getName(), () => {
 
     setBaseUrl(baseUrl);
   });
-  afterEach(() => {
-    httpMock.reset();
-  });
 
   async function initRepoMock(
     config?: Partial<RepoParams>,
diff --git a/lib/platform/bitbucket/utils.spec.ts b/lib/platform/bitbucket/utils.spec.ts
index ca2c34ea35e3ec86bfd89275bb129fc5f65fecde..39da0c4061a018bf050de3cdd585a565fdbeb34b 100644
--- a/lib/platform/bitbucket/utils.spec.ts
+++ b/lib/platform/bitbucket/utils.spec.ts
@@ -8,14 +8,9 @@ const baseUrl = 'https://api.bitbucket.org';
 
 describe('accumulateValues()', () => {
   beforeEach(() => {
-    httpMock.setup();
     setBaseUrl(baseUrl);
   });
 
-  afterEach(() => {
-    httpMock.reset();
-  });
-
   it('paginates', async () => {
     httpMock
       .scope(baseUrl)
diff --git a/lib/platform/gitea/gitea-helper.spec.ts b/lib/platform/gitea/gitea-helper.spec.ts
index 2213effdb80221631ca4f44ec48fa0e4e98bf235..225dcc3e5518ab33b140e672431c029af163faab 100644
--- a/lib/platform/gitea/gitea-helper.spec.ts
+++ b/lib/platform/gitea/gitea-helper.spec.ts
@@ -140,13 +140,8 @@ describe(getName(), () => {
 
   beforeEach(() => {
     jest.resetAllMocks();
-    httpMock.reset();
-    httpMock.setup();
     setBaseUrl(baseUrl);
   });
-  afterEach(() => {
-    httpMock.reset();
-  });
 
   describe('getCurrentUser', () => {
     it('should call /api/v1/user endpoint', async () => {
diff --git a/lib/platform/github/index.spec.ts b/lib/platform/github/index.spec.ts
index aa84436489261e22d60ade94b5d6c4c2305ab728..ed7d87995ea995f042e1347f68639c33d04849bb 100644
--- a/lib/platform/github/index.spec.ts
+++ b/lib/platform/github/index.spec.ts
@@ -34,11 +34,6 @@ describe(getName(), () => {
     hostRules.find.mockReturnValue({
       token: 'abc123',
     });
-    httpMock.setup();
-  });
-
-  afterEach(() => {
-    httpMock.reset();
   });
 
   const graphqlOpenPullRequests = loadFixture('graphql/pullrequest-1.json');
diff --git a/lib/platform/gitlab/index.spec.ts b/lib/platform/gitlab/index.spec.ts
index a436586ac9898b0ec2cbbc72c8b326767e4922a2..384d282da1b190cf032ac5be28d77a19d4cd278f 100644
--- a/lib/platform/gitlab/index.spec.ts
+++ b/lib/platform/gitlab/index.spec.ts
@@ -43,11 +43,6 @@ describe(getName(), () => {
     hostRules.find.mockReturnValue({
       token: 'abc123',
     });
-    httpMock.reset();
-    httpMock.setup();
-  });
-  afterEach(() => {
-    httpMock.reset();
   });
 
   async function initFakePlatform(version: string) {
diff --git a/lib/util/http/bitbucket-server.spec.ts b/lib/util/http/bitbucket-server.spec.ts
index f93832f00b35cd163d2e1042ad64e95b06db43b1..149f6fe182c731c6b39ee27c5077f5d2e140b35d 100644
--- a/lib/util/http/bitbucket-server.spec.ts
+++ b/lib/util/http/bitbucket-server.spec.ts
@@ -22,14 +22,9 @@ describe(getName(), () => {
       token: 'token',
     });
 
-    httpMock.reset();
-    httpMock.setup();
-
     setBaseUrl(baseUrl);
   });
-  afterEach(() => {
-    httpMock.reset();
-  });
+
   it('posts', async () => {
     const body = ['a', 'b'];
     httpMock.scope(baseUrl).post('/some-url').reply(200, body);
diff --git a/lib/util/http/bitbucket.spec.ts b/lib/util/http/bitbucket.spec.ts
index 3c17426d8e89659ef45ce9de333e6f2bf2467bed..377d96387b8ecdbeb17a8d35a58d75f140ce182f 100644
--- a/lib/util/http/bitbucket.spec.ts
+++ b/lib/util/http/bitbucket.spec.ts
@@ -22,14 +22,9 @@ describe(getName(), () => {
       token: 'token',
     });
 
-    httpMock.reset();
-    httpMock.setup();
-
     setBaseUrl(baseUrl);
   });
-  afterEach(() => {
-    httpMock.reset();
-  });
+
   it('posts', async () => {
     const body = ['a', 'b'];
     httpMock.scope(baseUrl).post('/some-url').reply(200, body);
diff --git a/lib/util/http/gitea.spec.ts b/lib/util/http/gitea.spec.ts
index 6f28781cd9ff0c5056ced1e25d6f09c98859d786..b3043b9bc1bc3d5fcb3315112cbe215efc5fcdda 100644
--- a/lib/util/http/gitea.spec.ts
+++ b/lib/util/http/gitea.spec.ts
@@ -12,16 +12,9 @@ describe(getName(), () => {
 
     jest.resetAllMocks();
 
-    httpMock.reset();
-    httpMock.setup();
-
     setBaseUrl(baseUrl);
   });
 
-  afterEach(() => {
-    httpMock.reset();
-  });
-
   it('supports responses without pagination when enabled', async () => {
     httpMock
       .scope(baseUrl)
diff --git a/lib/util/http/github.spec.ts b/lib/util/http/github.spec.ts
index b1f80a7c7236cdfa670fb4688b019abd2c164bde..23f08603a123efed1676e4da878f2aee61470170 100644
--- a/lib/util/http/github.spec.ts
+++ b/lib/util/http/github.spec.ts
@@ -19,11 +19,9 @@ describe(getName(), () => {
     githubApi = new GithubHttp();
     setBaseUrl(githubApiHost);
     jest.resetAllMocks();
-    httpMock.setup();
   });
 
   afterEach(() => {
-    httpMock.reset();
     hostRules.clear();
   });
 
diff --git a/lib/util/http/gitlab.spec.ts b/lib/util/http/gitlab.spec.ts
index 25b03855dac9012791f6b9474802ad661bba3ab6..d3a653f1e3a058cdba20c4f440098b6926f97394 100644
--- a/lib/util/http/gitlab.spec.ts
+++ b/lib/util/http/gitlab.spec.ts
@@ -18,12 +18,10 @@ describe(getName(), () => {
   beforeEach(() => {
     gitlabApi = new GitlabHttp();
     setBaseUrl(`${gitlabApiHost}/api/v4/`);
-    httpMock.setup();
   });
 
   afterEach(() => {
     jest.resetAllMocks();
-    httpMock.reset();
   });
 
   it('paginates', async () => {
diff --git a/lib/util/http/host-rules.spec.ts b/lib/util/http/host-rules.spec.ts
index f450f61bbae4bf38b5ee6f0faafb1046cdd44a63..46d584e6b802c95617e9abb96083385eae7026d9 100644
--- a/lib/util/http/host-rules.spec.ts
+++ b/lib/util/http/host-rules.spec.ts
@@ -1,4 +1,3 @@
-import * as httpMock from '../../../test/http-mock';
 import { getName } from '../../../test/util';
 import {
   PLATFORM_TYPE_GITEA,
@@ -38,14 +37,10 @@ describe(getName(), () => {
       authType: 'Basic',
       token: 'XXX',
     });
-
-    httpMock.reset();
-    httpMock.setup();
   });
 
   afterEach(() => {
     delete process.env.HTTP_PROXY;
-    httpMock.reset();
   });
 
   it('adds token', () => {
diff --git a/lib/workers/pr/changelog/gitlab.spec.ts b/lib/workers/pr/changelog/gitlab.spec.ts
index b629a1f8c6a2162cdb3cc254f103ef07b759aa82..1cd9a111ec645cdb2bd52128fe94b313fac0fd92 100644
--- a/lib/workers/pr/changelog/gitlab.spec.ts
+++ b/lib/workers/pr/changelog/gitlab.spec.ts
@@ -34,7 +34,6 @@ const matchHost = 'https://gitlab.com/';
 describe(getName(), () => {
   describe('getChangeLogJSON', () => {
     beforeEach(() => {
-      httpMock.setup();
       hostRules.clear();
       hostRules.add({
         hostType: PLATFORM_TYPE_GITLAB,
@@ -42,9 +41,7 @@ describe(getName(), () => {
         token: 'abc',
       });
     });
-    afterEach(() => {
-      httpMock.reset();
-    });
+
     it('returns null if @types', async () => {
       httpMock.scope(matchHost);
       expect(
diff --git a/lib/workers/pr/changelog/index.spec.ts b/lib/workers/pr/changelog/index.spec.ts
index 62a2e9e2975ce2250492607b5bca5a74bccbb0d0..5b41affe66addaa1880044390e2b22cd0a756b40 100644
--- a/lib/workers/pr/changelog/index.spec.ts
+++ b/lib/workers/pr/changelog/index.spec.ts
@@ -34,7 +34,6 @@ const upgrade: BranchConfig = partial<BranchConfig>({
 describe(getName(), () => {
   describe('getChangeLogJSON', () => {
     beforeEach(() => {
-      httpMock.setup();
       hostRules.clear();
       hostRules.add({
         hostType: PLATFORM_TYPE_GITHUB,
@@ -43,10 +42,6 @@ describe(getName(), () => {
       });
     });
 
-    afterEach(() => {
-      httpMock.reset();
-    });
-
     it('returns null if @types', async () => {
       httpMock.scope(githubApiHost);
       expect(
diff --git a/lib/workers/pr/changelog/release-notes.spec.ts b/lib/workers/pr/changelog/release-notes.spec.ts
index 7929098c49c986fdef7557727235f7c6dd120fd4..15b4cbba12cf836add3f673d94d9ebadeea47d3f 100644
--- a/lib/workers/pr/changelog/release-notes.spec.ts
+++ b/lib/workers/pr/changelog/release-notes.spec.ts
@@ -38,13 +38,11 @@ const gitlabTreeResponse = [
 
 describe(getName(), () => {
   beforeEach(() => {
-    httpMock.setup();
     hostRules.find.mockReturnValue({});
     hostRules.hosts.mockReturnValue([]);
   });
 
   afterEach(() => {
-    httpMock.reset();
     jest.resetAllMocks();
   });
 
diff --git a/test/http-mock.ts b/test/http-mock.ts
index 85c87181609cbd2805878a114beec65d67761640..90a115989534c028c5f1857954eed6a9e7df2d24 100644
--- a/test/http-mock.ts
+++ b/test/http-mock.ts
@@ -1,4 +1,5 @@
 import { Url } from 'url';
+import { afterAll, afterEach, beforeAll } from '@jest/globals';
 import is from '@sindresorhus/is';
 import { parse as parseGraphqlQuery } from 'graphql/language';
 import nock from 'nock';
@@ -95,28 +96,24 @@ function onMissing(req: TestRequest, opts?: TestRequest): void {
   }
 }
 
-export function setup(): void {
-  if (!nock.isActive()) {
-    nock.activate();
-  }
-  nock.disableNetConnect();
-  nock.emitter.on('no match', onMissing);
+export function allUsed(): boolean {
+  return nock.isDone();
 }
 
-export function reset(): void {
-  nock.emitter.removeListener('no match', onMissing);
+/**
+ *  Clear nock state. Will be called in `afterEach`
+ *  @argument throwOnPending Use `false` to simply clear mocks.
+ */
+export function clear(throwOnPending = true): void {
+  const isDone = nock.isDone();
+  const pending = nock.pendingMocks();
   nock.abortPendingRequests();
-  if (nock.isActive()) {
-    nock.restore();
-  }
   nock.cleanAll();
   requestLog = [];
   missingLog = [];
-  nock.enableNetConnect();
-}
-
-export function allUsed(): boolean {
-  return nock.isDone();
+  if (!isDone && throwOnPending) {
+    throw new Error(`Pending mocks!\n * ${pending.join('\n * ')}`);
+  }
 }
 
 export function scope(basePath: BasePath, options?: nock.Options): nock.Scope {
@@ -162,3 +159,20 @@ export function getTrace(): RequestLogItem[] /* istanbul ignore next */ {
   }
   return requestLog;
 }
+
+// init nock
+beforeAll(() => {
+  nock.emitter.on('no match', onMissing);
+  nock.disableNetConnect();
+});
+
+// clean nock to clear memory leack from http module patching
+afterAll(() => {
+  nock.emitter.removeListener('no match', onMissing);
+  nock.restore();
+});
+
+// clear nock state
+afterEach(() => {
+  clear();
+});