From 84a97a62fa912effc8192ca37db870f0211a747f Mon Sep 17 00:00:00 2001
From: Michael Kriese <michael.kriese@visualon.de>
Date: Fri, 8 Sep 2023 13:40:04 +0200
Subject: [PATCH] test(perf): improve test speed (#24323)

---
 jest.config.ts                                |   2 +-
 lib/config/index.spec.ts                      |   6 +-
 lib/config/options/index.spec.ts              |   4 +-
 lib/config/presets/gitea/index.spec.ts        |   3 +-
 lib/config/presets/github/index.spec.ts       |   3 +-
 lib/instrumentation/decorator.spec.ts         |   1 -
 lib/instrumentation/index.spec.ts             |   1 -
 lib/logger/__mocks__/index.ts                 |  25 --
 lib/modules/datasource/docker/common.spec.ts  |   3 +-
 lib/modules/datasource/docker/index.spec.ts   |   3 +-
 .../github-release-attachments/index.spec.ts  |   3 +-
 .../datasource/github-releases/index.spec.ts  |   3 +-
 .../datasource/github-tags/index.spec.ts      |   1 -
 lib/modules/datasource/go/base.spec.ts        |   8 +-
 lib/modules/datasource/go/index.spec.ts       |   8 +-
 .../datasource/go/releases-direct.spec.ts     |   3 +-
 lib/modules/datasource/helm/index.spec.ts     |   4 -
 lib/modules/datasource/hex/index.spec.ts      |   7 +-
 lib/modules/datasource/maven/index.spec.ts    |   1 -
 lib/modules/datasource/maven/s3.spec.ts       |   1 -
 lib/modules/datasource/npm/index.spec.ts      |   1 -
 lib/modules/datasource/npm/npmrc.spec.ts      |   1 -
 lib/modules/datasource/nuget/index.spec.ts    |   8 +-
 .../datasource/packagist/index.spec.ts        |   4 +-
 lib/modules/datasource/pod/index.spec.ts      |   1 -
 lib/modules/datasource/pypi/index.spec.ts     |   1 -
 lib/modules/datasource/rubygems/index.spec.ts |   1 -
 .../rubygems/metadata-cache.spec.ts           |  18 +-
 .../manager/bazel-module/extract.spec.ts      |  11 +-
 lib/modules/manager/bundler/artifacts.spec.ts |   6 +-
 lib/modules/manager/cargo/artifacts.spec.ts   |   3 -
 .../manager/cocoapods/artifacts.spec.ts       |   5 +-
 .../manager/composer/artifacts.spec.ts        |   5 +-
 lib/modules/manager/composer/utils.spec.ts    |   3 +-
 .../manager/git-submodules/extract.spec.ts    |   3 +-
 lib/modules/manager/gomod/artifacts.spec.ts   |  18 +-
 .../manager/gradle-wrapper/artifacts.spec.ts  |   3 +-
 lib/modules/manager/gradle/artifacts.spec.ts  |   3 +-
 lib/modules/manager/gradle/extract.spec.ts    |   4 +-
 .../consistent-versions-plugin.spec.ts        |   4 -
 .../manager/helm-requirements/extract.spec.ts |   5 -
 .../manager/helm-values/extract.spec.ts       |   4 -
 .../manager/helmfile/artifacts.spec.ts        |   3 +-
 lib/modules/manager/helmfile/extract.spec.ts  |   1 -
 lib/modules/manager/helmv3/artifacts.spec.ts  |   6 +-
 lib/modules/manager/helmv3/extract.spec.ts    |   5 -
 lib/modules/manager/homebrew/update.spec.ts   |   5 -
 .../manager/maven-wrapper/artifacts.spec.ts   |   3 +-
 lib/modules/manager/mix/artifacts.spec.ts     |   7 +-
 lib/modules/manager/nix/artifacts.spec.ts     |   4 +-
 lib/modules/manager/npm/extract/index.spec.ts |   5 +-
 .../npm/extract/locked-versions.spec.ts       |   2 +-
 lib/modules/manager/npm/extract/pnpm.spec.ts  |  51 +--
 .../__snapshots__/yarn.spec.ts.snap           | 315 ------------------
 .../manager/npm/post-update/index.spec.ts     |   1 -
 .../manager/npm/post-update/lerna.spec.ts     |   5 +-
 .../manager/npm/post-update/npm.spec.ts       |   2 -
 .../manager/npm/post-update/pnpm.spec.ts      |   1 -
 .../manager/npm/post-update/yarn.spec.ts      |  13 +-
 .../npm/update/package-version/index.spec.ts  |   2 +-
 lib/modules/manager/nuget/artifacts.spec.ts   |  10 +-
 .../manager/nuget/package-tree.spec.ts        |   8 +-
 lib/modules/manager/pep621/artifacts.spec.ts  |   3 +-
 .../manager/pip-compile/artifacts.spec.ts     |   6 +-
 .../pip_requirements/artifacts.spec.ts        |   5 +-
 lib/modules/manager/pipenv/artifacts.spec.ts  |   6 +-
 lib/modules/manager/poetry/artifacts.spec.ts  |   6 +-
 .../manager/pre-commit/extract.spec.ts        |   7 +-
 lib/modules/manager/pub/artifacts.spec.ts     |   5 +-
 .../manager/terraform/lockfile/hash.spec.ts   |   3 +-
 .../manager/terraform/lockfile/index.spec.ts  |   5 +-
 .../platform/azure/azure-got-wrapper.spec.ts  |   6 +-
 .../platform/azure/azure-helper.spec.ts       |   9 +-
 lib/modules/platform/azure/index.spec.ts      |  31 +-
 .../platform/bitbucket-server/index.spec.ts   |  17 +-
 lib/modules/platform/bitbucket/index.spec.ts  |  10 +-
 lib/modules/platform/comment.spec.ts          |   2 +-
 .../platform/gitea/gitea-helper.spec.ts       |   1 -
 lib/modules/platform/gitea/index.spec.ts      |  16 +-
 lib/modules/platform/github/index.spec.ts     |   4 +-
 lib/modules/platform/gitlab/index.spec.ts     |  36 +-
 lib/modules/platform/local/scm.spec.ts        |   8 +-
 lib/modules/versioning/index.spec.ts          |   4 +-
 lib/modules/versioning/ubuntu/index.spec.ts   |   4 -
 .../versioning/versioning-metadata.spec.ts    |   2 +-
 lib/renovate.spec.ts                          |   4 +-
 lib/util/cache/package/decorator.spec.ts      |  18 +-
 lib/util/cache/repository/impl/local.spec.ts  |   1 -
 lib/util/cache/repository/index.spec.ts       |   1 -
 lib/util/check-token.spec.ts                  |   4 +-
 lib/util/exec/docker/index.spec.ts            |   7 +-
 lib/util/exec/index.spec.ts                   |   7 +-
 lib/util/git/index.spec.ts                    |   4 -
 lib/util/git/private-key.spec.ts              |   9 +-
 lib/util/git/semantic.spec.ts                 |   1 -
 lib/util/git/url.spec.ts                      |   3 +-
 .../memory-cache-strategy.spec.ts             |   1 -
 .../github/graphql/datasource-fetcher.spec.ts |   1 -
 lib/util/http/bitbucket-server.spec.ts        |   3 -
 lib/util/http/bitbucket.spec.ts               |   3 -
 lib/util/http/gitea.spec.ts                   |   2 -
 lib/util/http/github.spec.ts                  |   1 -
 lib/util/http/gitlab.spec.ts                  |   2 -
 lib/util/http/host-rules.spec.ts              |   3 -
 lib/util/http/index.spec.ts                   |   1 -
 lib/util/json-writer/editor-config.spec.ts    |  23 +-
 lib/util/merge-confidence/index.spec.ts       |   1 -
 lib/util/regex.spec.ts                        |   4 +-
 lib/workers/global/autodiscover.spec.ts       |   1 -
 lib/workers/global/config/parse/file.spec.ts  |   4 +-
 lib/workers/global/config/parse/index.spec.ts |   6 +-
 lib/workers/global/index.spec.ts              |   1 -
 .../branch/commit-message.spec.ts             |   4 -
 .../config-migration/branch/index.spec.ts     |   1 -
 .../branch/migrated-data.spec.ts              |   1 -
 .../repository/config-migration/index.spec.ts |   1 -
 .../config-migration/pr/index.spec.ts         |   3 +-
 lib/workers/repository/configured.spec.ts     |   1 -
 .../repository/dependency-dashboard.spec.ts   |   4 -
 lib/workers/repository/error-config.spec.ts   |   1 -
 lib/workers/repository/error.spec.ts          |   1 -
 .../repository/errors-warnings.spec.ts        |  10 -
 lib/workers/repository/extract/index.spec.ts  |   1 -
 .../repository/extract/manager-files.spec.ts  |   1 -
 lib/workers/repository/finalize/prune.spec.ts |   1 -
 lib/workers/repository/init/apis.spec.ts      |   4 -
 lib/workers/repository/init/index.spec.ts     |   4 +
 lib/workers/repository/init/merge.spec.ts     |   1 -
 .../repository/init/vulnerability.spec.ts     |   1 -
 .../onboarding/branch/index.spec.ts           |   1 -
 .../branch/onboarding-branch-cache.spec.ts    |   2 +
 .../onboarding/pr/base-branch.spec.ts         |   1 -
 .../onboarding/pr/config-description.spec.ts  |   1 -
 .../repository/onboarding/pr/index.spec.ts    |   5 +-
 .../repository/onboarding/pr/pr-list.spec.ts  |   1 -
 .../repository/process/extract-update.spec.ts |  26 +-
 lib/workers/repository/process/fetch.spec.ts  |   1 -
 lib/workers/repository/process/index.spec.ts  |   1 -
 lib/workers/repository/process/limits.spec.ts |   1 -
 .../process/lookup/filter-checks.spec.ts      |   1 -
 .../repository/process/lookup/index.spec.ts   |   2 -
 lib/workers/repository/process/write.spec.ts  |   1 -
 lib/workers/repository/result.spec.ts         |   1 -
 .../update/branch/artifacts.spec.ts           |   1 -
 .../update/branch/auto-replace.spec.ts        |   2 +-
 .../update/branch/automerge.spec.ts           |   1 +
 .../update/branch/check-existing.spec.ts      |   1 -
 .../repository/update/branch/commit.spec.ts   |   1 -
 .../repository/update/branch/index.spec.ts    |   1 -
 .../update/branch/lock-files/index.spec.ts    |   5 -
 .../repository/update/branch/reuse.spec.ts    |   1 -
 .../repository/update/branch/schedule.spec.ts |   6 +-
 .../update/branch/status-checks.spec.ts       |   8 +-
 .../repository/update/pr/automerge.spec.ts    |   1 +
 .../update/pr/body/changelogs.spec.ts         |   4 -
 .../update/pr/body/config-description.spec.ts |   4 -
 .../repository/update/pr/body/footer.spec.ts  |   4 -
 .../repository/update/pr/body/header.spec.ts  |   4 -
 .../repository/update/pr/body/notes.spec.ts   |   4 -
 .../update/pr/changelog/github/index.spec.ts  |   1 -
 .../update/pr/changelog/release-notes.spec.ts |   3 +-
 .../repository/update/pr/code-owners.spec.ts  |   1 -
 .../repository/update/pr/index.spec.ts        |   1 -
 .../repository/update/pr/participants.spec.ts |   1 -
 .../repository/updates/branchify.spec.ts      |   1 -
 .../repository/updates/flatten.spec.ts        |   1 -
 .../repository/updates/generate.spec.ts       |   1 -
 test/fixtures.ts                              |  40 ++-
 test/setup.ts                                 | 165 +--------
 test/types/jest.d.ts                          | 156 +++++++++
 test/util.ts                                  |  18 +-
 171 files changed, 492 insertions(+), 993 deletions(-)
 delete mode 100644 lib/logger/__mocks__/index.ts
 create mode 100644 test/types/jest.d.ts

diff --git a/jest.config.ts b/jest.config.ts
index d354593760..8dfa2efa0a 100644
--- a/jest.config.ts
+++ b/jest.config.ts
@@ -211,7 +211,6 @@ const config: JestConfig = {
     '<rootDir>/tools/',
   ],
   cacheDirectory: '.cache/jest',
-  clearMocks: true,
   collectCoverage: true,
   coverageReporters: ci
     ? ['lcovonly', 'json']
@@ -232,6 +231,7 @@ const config: JestConfig = {
     '/__mocks__/',
   ],
   reporters: ci ? ['default', 'github-actions'] : ['default'],
+  resetMocks: true,
   setupFilesAfterEnv: [
     'jest-extended/all',
     'expect-more-jest',
diff --git a/lib/config/index.spec.ts b/lib/config/index.spec.ts
index 94e6822cf7..9652cfaef1 100644
--- a/lib/config/index.spec.ts
+++ b/lib/config/index.spec.ts
@@ -2,11 +2,7 @@ import { getConfig } from './defaults';
 import { filterConfig, getManagerConfig, mergeChildConfig } from './index';
 
 jest.mock('../modules/datasource/npm');
-try {
-  jest.mock('../../config.js');
-} catch (err) {
-  // file does not exist
-}
+jest.mock('../../config.js', () => ({}), { virtual: true });
 
 const defaultConfig = getConfig();
 
diff --git a/lib/config/options/index.spec.ts b/lib/config/options/index.spec.ts
index ddfc1b2f5e..20508f2684 100644
--- a/lib/config/options/index.spec.ts
+++ b/lib/config/options/index.spec.ts
@@ -6,7 +6,7 @@ jest.unmock('../../modules/platform');
 
 describe('config/options/index', () => {
   it('test manager should have no defaultConfig', () => {
-    jest.mock('../../modules/manager', () => ({
+    jest.doMock('../../modules/manager', () => ({
       getManagers: jest.fn(() => new Map().set('testManager', {})),
     }));
 
@@ -15,7 +15,6 @@ describe('config/options/index', () => {
   });
 
   it('supportedManagers should have valid names', () => {
-    jest.unmock('../../modules/manager');
     const opts = getOptions();
     const managerList = Array.from(manager.getManagers().keys());
 
@@ -30,7 +29,6 @@ describe('config/options/index', () => {
   });
 
   it('supportedPlatforms should have valid names', () => {
-    jest.unmock('../../modules/platform');
     const opts = getOptions();
     const platformList = Array.from(platform.getPlatforms().keys());
 
diff --git a/lib/config/presets/gitea/index.spec.ts b/lib/config/presets/gitea/index.spec.ts
index 49670d27a4..a84adaff4a 100644
--- a/lib/config/presets/gitea/index.spec.ts
+++ b/lib/config/presets/gitea/index.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import * as httpMock from '../../../../test/http-mock';
 import { mocked } from '../../../../test/util';
 import * as _hostRules from '../../../util/host-rules';
@@ -6,7 +7,7 @@ import { toBase64 } from '../../../util/string';
 import { PRESET_INVALID_JSON, PRESET_NOT_FOUND } from '../util';
 import * as gitea from '.';
 
-jest.mock('../../../util/host-rules');
+jest.mock('../../../util/host-rules', () => mockDeep());
 
 const hostRules = mocked(_hostRules);
 
diff --git a/lib/config/presets/github/index.spec.ts b/lib/config/presets/github/index.spec.ts
index 93ef768c19..b9c06e3aa6 100644
--- a/lib/config/presets/github/index.spec.ts
+++ b/lib/config/presets/github/index.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import * as httpMock from '../../../../test/http-mock';
 import { mocked } from '../../../../test/util';
 import * as _hostRules from '../../../util/host-rules';
@@ -5,7 +6,7 @@ import { toBase64 } from '../../../util/string';
 import { PRESET_INVALID_JSON, PRESET_NOT_FOUND } from '../util';
 import * as github from '.';
 
-jest.mock('../../../util/host-rules');
+jest.mock('../../../util/host-rules', () => mockDeep());
 
 const hostRules = mocked(_hostRules);
 
diff --git a/lib/instrumentation/decorator.spec.ts b/lib/instrumentation/decorator.spec.ts
index c18800cedf..ff812bed6f 100644
--- a/lib/instrumentation/decorator.spec.ts
+++ b/lib/instrumentation/decorator.spec.ts
@@ -1,4 +1,3 @@
-import { afterAll } from '@jest/globals';
 import { instrument } from './decorator';
 import { disableInstrumentations } from '.';
 
diff --git a/lib/instrumentation/index.spec.ts b/lib/instrumentation/index.spec.ts
index 82b1230e26..c098aae373 100644
--- a/lib/instrumentation/index.spec.ts
+++ b/lib/instrumentation/index.spec.ts
@@ -1,4 +1,3 @@
-import { afterAll } from '@jest/globals';
 import { ProxyTracerProvider } from '@opentelemetry/api';
 import * as api from '@opentelemetry/api';
 import { NoopTracerProvider } from '@opentelemetry/api/build/src/trace/NoopTracerProvider';
diff --git a/lib/logger/__mocks__/index.ts b/lib/logger/__mocks__/index.ts
deleted file mode 100644
index 637c95b8cd..0000000000
--- a/lib/logger/__mocks__/index.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-const loggerLevels: string[] = [
-  'trace',
-  'debug',
-  'info',
-  'warn',
-  'error',
-  'fatal',
-  'child',
-];
-const logger: any = {};
-
-loggerLevels.forEach(k => {
-  logger[k] = jest.fn();
-});
-
-export const setContext = jest.fn();
-export const getContext = jest.fn();
-export const setMeta = jest.fn();
-export const addMeta = jest.fn();
-export const removeMeta = jest.fn();
-export const levels = jest.fn();
-export const addStream = jest.fn();
-export const getProblems = jest.fn((): any[] => []);
-
-export { logger };
diff --git a/lib/modules/datasource/docker/common.spec.ts b/lib/modules/datasource/docker/common.spec.ts
index 8414323f55..c30292f98b 100644
--- a/lib/modules/datasource/docker/common.spec.ts
+++ b/lib/modules/datasource/docker/common.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import * as httpMock from '../../../../test/http-mock';
 import { mocked, partial } from '../../../../test/util';
 import { PAGE_NOT_FOUND_ERROR } from '../../../constants/error-messages';
@@ -16,7 +17,7 @@ const hostRules = mocked(_hostRules);
 
 const http = new Http(dockerDatasourceId);
 
-jest.mock('../../../util/host-rules');
+jest.mock('../../../util/host-rules', () => mockDeep());
 
 describe('modules/datasource/docker/common', () => {
   describe('getRegistryRepository', () => {
diff --git a/lib/modules/datasource/docker/index.spec.ts b/lib/modules/datasource/docker/index.spec.ts
index 3cf817a3aa..10d3472a1c 100644
--- a/lib/modules/datasource/docker/index.spec.ts
+++ b/lib/modules/datasource/docker/index.spec.ts
@@ -4,6 +4,7 @@ import {
   GetAuthorizationTokenCommandOutput,
 } from '@aws-sdk/client-ecr';
 import { mockClient } from 'aws-sdk-client-mock';
+import { mockDeep } from 'jest-mock-extended';
 import { getDigest, getPkgReleases } from '..';
 import { range } from '../../../../lib/util/range';
 import * as httpMock from '../../../../test/http-mock';
@@ -14,7 +15,7 @@ import { DockerDatasource } from '.';
 
 const hostRules = mocked(_hostRules);
 
-jest.mock('../../../util/host-rules');
+jest.mock('../../../util/host-rules', () => mockDeep());
 
 const ecrMock = mockClient(ECRClient);
 
diff --git a/lib/modules/datasource/github-release-attachments/index.spec.ts b/lib/modules/datasource/github-release-attachments/index.spec.ts
index 576bf7a004..6494eb3bc8 100644
--- a/lib/modules/datasource/github-release-attachments/index.spec.ts
+++ b/lib/modules/datasource/github-release-attachments/index.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import { getDigest, getPkgReleases } from '..';
 import { mocked } from '../../../../test/util';
 import * as githubGraphql from '../../../util/github/graphql';
@@ -5,7 +6,7 @@ import * as _hostRules from '../../../util/host-rules';
 import { GitHubReleaseAttachmentMocker } from './test';
 import { GithubReleaseAttachmentsDatasource } from '.';
 
-jest.mock('../../../util/host-rules');
+jest.mock('../../../util/host-rules', () => mockDeep());
 const hostRules = mocked(_hostRules);
 
 const githubApiHost = 'https://api.github.com';
diff --git a/lib/modules/datasource/github-releases/index.spec.ts b/lib/modules/datasource/github-releases/index.spec.ts
index 42f485fa58..999c708fbc 100644
--- a/lib/modules/datasource/github-releases/index.spec.ts
+++ b/lib/modules/datasource/github-releases/index.spec.ts
@@ -1,10 +1,11 @@
+import { mockDeep } from 'jest-mock-extended';
 import { getDigest, getPkgReleases } from '..';
 import { mocked } from '../../../../test/util';
 import * as githubGraphql from '../../../util/github/graphql';
 import * as _hostRules from '../../../util/host-rules';
 import { GithubReleasesDatasource } from '.';
 
-jest.mock('../../../util/host-rules');
+jest.mock('../../../util/host-rules', () => mockDeep());
 const hostRules = mocked(_hostRules);
 
 describe('modules/datasource/github-releases/index', () => {
diff --git a/lib/modules/datasource/github-tags/index.spec.ts b/lib/modules/datasource/github-tags/index.spec.ts
index 5f5681e432..8bde1f8d3f 100644
--- a/lib/modules/datasource/github-tags/index.spec.ts
+++ b/lib/modules/datasource/github-tags/index.spec.ts
@@ -12,7 +12,6 @@ describe('modules/datasource/github-tags/index', () => {
   const github = new GithubTagsDatasource();
 
   beforeEach(() => {
-    jest.resetAllMocks();
     jest.spyOn(hostRules, 'hosts').mockReturnValue([]);
     jest.spyOn(hostRules, 'find').mockReturnValue({
       token: 'some-token',
diff --git a/lib/modules/datasource/go/base.spec.ts b/lib/modules/datasource/go/base.spec.ts
index 68ad5bf917..b5c85a4987 100644
--- a/lib/modules/datasource/go/base.spec.ts
+++ b/lib/modules/datasource/go/base.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import { Fixtures } from '../../../../test/fixtures';
 import * as httpMock from '../../../../test/http-mock';
 import { mocked } from '../../../../test/util';
@@ -7,7 +8,7 @@ import { GithubTagsDatasource } from '../github-tags';
 import { GitlabTagsDatasource } from '../gitlab-tags';
 import { BaseGoDatasource } from './base';
 
-jest.mock('../../../util/host-rules');
+jest.mock('../../../util/host-rules', () => mockDeep());
 
 const hostRules = mocked(_hostRules);
 
@@ -30,15 +31,10 @@ describe('modules/datasource/go/base', () => {
 
   describe('go-get requests', () => {
     beforeEach(() => {
-      jest.resetAllMocks();
       hostRules.find.mockReturnValue({});
       hostRules.hosts.mockReturnValue([]);
     });
 
-    afterEach(() => {
-      jest.resetAllMocks();
-    });
-
     describe('meta name=go-source', () => {
       it('returns null for unknown prefix', async () => {
         const meta =
diff --git a/lib/modules/datasource/go/index.spec.ts b/lib/modules/datasource/go/index.spec.ts
index ab23fe6909..b836ff8805 100644
--- a/lib/modules/datasource/go/index.spec.ts
+++ b/lib/modules/datasource/go/index.spec.ts
@@ -1,10 +1,11 @@
+import { mockDeep } from 'jest-mock-extended';
 import { Fixtures } from '../../../../test/fixtures';
 import * as httpMock from '../../../../test/http-mock';
 import { mocked } from '../../../../test/util';
 import * as _hostRules from '../../../util/host-rules';
 import { GoDatasource } from '.';
 
-jest.mock('../../../util/host-rules');
+jest.mock('../../../util/host-rules', () => mockDeep());
 const hostRules = mocked(_hostRules);
 
 const getReleasesDirectMock = jest.fn();
@@ -70,15 +71,10 @@ describe('modules/datasource/go/index', () => {
 
   describe('getDigest', () => {
     beforeEach(() => {
-      jest.resetAllMocks();
       hostRules.find.mockReturnValue({});
       hostRules.hosts.mockReturnValue([]);
     });
 
-    afterEach(() => {
-      jest.resetAllMocks();
-    });
-
     it('returns null for no go-source tag', async () => {
       httpMock
         .scope('https://golang.org/')
diff --git a/lib/modules/datasource/go/releases-direct.spec.ts b/lib/modules/datasource/go/releases-direct.spec.ts
index 27debf6201..fa83dd4655 100644
--- a/lib/modules/datasource/go/releases-direct.spec.ts
+++ b/lib/modules/datasource/go/releases-direct.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import * as httpMock from '../../../../test/http-mock';
 import { mocked } from '../../../../test/util';
 import * as _hostRules from '../../../util/host-rules';
@@ -6,7 +7,7 @@ import { GithubTagsDatasource } from '../github-tags';
 import { BaseGoDatasource } from './base';
 import { GoDirectDatasource } from './releases-direct';
 
-jest.mock('../../../util/host-rules');
+jest.mock('../../../util/host-rules', () => mockDeep());
 jest.mock('./base');
 
 const datasource = new GoDirectDatasource();
diff --git a/lib/modules/datasource/helm/index.spec.ts b/lib/modules/datasource/helm/index.spec.ts
index b737d4cd92..93366c38bc 100644
--- a/lib/modules/datasource/helm/index.spec.ts
+++ b/lib/modules/datasource/helm/index.spec.ts
@@ -9,10 +9,6 @@ const indexYaml = Fixtures.get('index.yaml');
 
 describe('modules/datasource/helm/index', () => {
   describe('getReleases', () => {
-    beforeEach(() => {
-      jest.resetAllMocks();
-    });
-
     it('returns null if packageName was not provided', async () => {
       expect(
         await getPkgReleases({
diff --git a/lib/modules/datasource/hex/index.spec.ts b/lib/modules/datasource/hex/index.spec.ts
index 609220fc7a..96f435c6b8 100644
--- a/lib/modules/datasource/hex/index.spec.ts
+++ b/lib/modules/datasource/hex/index.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import { getPkgReleases } from '..';
 import { Fixtures } from '../../../../test/fixtures';
 import * as httpMock from '../../../../test/http-mock';
@@ -8,7 +9,7 @@ import { HexDatasource } from '.';
 const certifiResponse = Fixtures.get('certifi.json');
 const privatePackageResponse = Fixtures.get('private_package.json');
 
-jest.mock('../../../util/host-rules');
+jest.mock('../../../util/host-rules', () => mockDeep());
 
 const baseUrl = 'https://hex.pm/api';
 const datasource = HexDatasource.id;
@@ -19,10 +20,6 @@ describe('modules/datasource/hex/index', () => {
     hostRules.find.mockReturnValue({});
   });
 
-  afterEach(() => {
-    jest.resetAllMocks();
-  });
-
   describe('getReleases', () => {
     it('returns null for empty result', async () => {
       httpMock.scope(baseUrl).get('/packages/non_existent_package').reply(200);
diff --git a/lib/modules/datasource/maven/index.spec.ts b/lib/modules/datasource/maven/index.spec.ts
index 0366e8b408..fd29186ced 100644
--- a/lib/modules/datasource/maven/index.spec.ts
+++ b/lib/modules/datasource/maven/index.spec.ts
@@ -176,7 +176,6 @@ describe('modules/datasource/maven/index', () => {
       matchHost: 'custom.registry.renovatebot.com',
       token: '123test',
     });
-    jest.resetAllMocks();
   });
 
   afterEach(() => {
diff --git a/lib/modules/datasource/maven/s3.spec.ts b/lib/modules/datasource/maven/s3.spec.ts
index 61a8534ced..a73c29a17c 100644
--- a/lib/modules/datasource/maven/s3.spec.ts
+++ b/lib/modules/datasource/maven/s3.spec.ts
@@ -36,7 +36,6 @@ describe('modules/datasource/maven/s3', () => {
       matchHost: 'custom.registry.renovatebot.com',
       token: '123test',
     });
-    jest.resetAllMocks();
   });
 
   afterEach(() => {
diff --git a/lib/modules/datasource/npm/index.spec.ts b/lib/modules/datasource/npm/index.spec.ts
index 54a37ed160..ed71b13b93 100644
--- a/lib/modules/datasource/npm/index.spec.ts
+++ b/lib/modules/datasource/npm/index.spec.ts
@@ -11,7 +11,6 @@ let npmResponse: any;
 
 describe('modules/datasource/npm/index', () => {
   beforeEach(() => {
-    jest.resetAllMocks();
     GlobalConfig.reset();
     hostRules.clear();
     setNpmrc();
diff --git a/lib/modules/datasource/npm/npmrc.spec.ts b/lib/modules/datasource/npm/npmrc.spec.ts
index 912badedad..3b9c4f381c 100644
--- a/lib/modules/datasource/npm/npmrc.spec.ts
+++ b/lib/modules/datasource/npm/npmrc.spec.ts
@@ -16,7 +16,6 @@ describe('modules/datasource/npm/npmrc', () => {
   beforeEach(() => {
     setNpmrc('');
     GlobalConfig.reset();
-    jest.resetAllMocks();
   });
 
   describe('getMatchHostFromNpmrcHost()', () => {
diff --git a/lib/modules/datasource/nuget/index.spec.ts b/lib/modules/datasource/nuget/index.spec.ts
index 43e38f25ee..b0b56b29ec 100644
--- a/lib/modules/datasource/nuget/index.spec.ts
+++ b/lib/modules/datasource/nuget/index.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import { getPkgReleases } from '..';
 import { Fixtures } from '../../../../test/fixtures';
 import * as httpMock from '../../../../test/http-mock';
@@ -10,7 +11,7 @@ const datasource = NugetDatasource.id;
 
 const hostRules: any = _hostRules;
 
-jest.mock('../../../util/host-rules');
+jest.mock('../../../util/host-rules', () => mockDeep());
 
 const pkgInfoV3FromNuget = Fixtures.get('nunit/v3_nuget_org.xml');
 const pkgListV3Registration = Fixtures.get('nunit/v3_registration.json');
@@ -95,10 +96,6 @@ const configV3Multiple = {
 
 describe('modules/datasource/nuget/index', () => {
   describe('parseRegistryUrl', () => {
-    beforeEach(() => {
-      jest.resetAllMocks();
-    });
-
     it('extracts feed version from registry URL hash (v3)', () => {
       const parsed = parseRegistryUrl('https://my-registry#protocolVersion=3');
 
@@ -130,7 +127,6 @@ describe('modules/datasource/nuget/index', () => {
 
   describe('getReleases', () => {
     beforeEach(() => {
-      jest.resetAllMocks();
       hostRules.hosts.mockReturnValue([]);
       hostRules.find.mockReturnValue({});
     });
diff --git a/lib/modules/datasource/packagist/index.spec.ts b/lib/modules/datasource/packagist/index.spec.ts
index 9f973a8605..e445de1790 100644
--- a/lib/modules/datasource/packagist/index.spec.ts
+++ b/lib/modules/datasource/packagist/index.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import { getPkgReleases } from '..';
 import { Fixtures } from '../../../../test/fixtures';
 import * as httpMock from '../../../../test/http-mock';
@@ -7,7 +8,7 @@ import * as composerVersioning from '../../versioning/composer';
 import { id as versioning } from '../../versioning/loose';
 import { PackagistDatasource } from '.';
 
-jest.mock('../../../util/host-rules');
+jest.mock('../../../util/host-rules', () => mockDeep());
 
 const hostRules = _hostRules;
 
@@ -24,7 +25,6 @@ describe('modules/datasource/packagist/index', () => {
     let config: any;
 
     beforeEach(() => {
-      jest.resetAllMocks();
       hostRules.find = jest.fn((input: HostRule) => input);
       hostRules.hosts = jest.fn(() => []);
       config = {
diff --git a/lib/modules/datasource/pod/index.spec.ts b/lib/modules/datasource/pod/index.spec.ts
index 9ac7b8c9af..366cd0886e 100644
--- a/lib/modules/datasource/pod/index.spec.ts
+++ b/lib/modules/datasource/pod/index.spec.ts
@@ -20,7 +20,6 @@ const cocoapodsHost = 'https://cdn.cocoapods.org';
 describe('modules/datasource/pod/index', () => {
   describe('getReleases', () => {
     beforeEach(() => {
-      jest.resetAllMocks();
       hostRules.clear();
     });
 
diff --git a/lib/modules/datasource/pypi/index.spec.ts b/lib/modules/datasource/pypi/index.spec.ts
index 7e2df584b7..1627305641 100644
--- a/lib/modules/datasource/pypi/index.spec.ts
+++ b/lib/modules/datasource/pypi/index.spec.ts
@@ -26,7 +26,6 @@ describe('modules/datasource/pypi/index', () => {
     beforeEach(() => {
       process.env = { ...OLD_ENV };
       delete process.env.PIP_INDEX_URL;
-      jest.resetAllMocks();
     });
 
     afterEach(() => {
diff --git a/lib/modules/datasource/rubygems/index.spec.ts b/lib/modules/datasource/rubygems/index.spec.ts
index 3db344a1a1..942ced25db 100644
--- a/lib/modules/datasource/rubygems/index.spec.ts
+++ b/lib/modules/datasource/rubygems/index.spec.ts
@@ -19,7 +19,6 @@ describe('modules/datasource/rubygems/index', () => {
   describe('getReleases', () => {
     beforeEach(() => {
       memCache.clear();
-      jest.resetAllMocks();
     });
 
     it('returns null for missing pkg', async () => {
diff --git a/lib/modules/datasource/rubygems/metadata-cache.spec.ts b/lib/modules/datasource/rubygems/metadata-cache.spec.ts
index ab7960f203..7b376ac6eb 100644
--- a/lib/modules/datasource/rubygems/metadata-cache.spec.ts
+++ b/lib/modules/datasource/rubygems/metadata-cache.spec.ts
@@ -10,17 +10,17 @@ const packageCache = mocked(_packageCache);
 describe('modules/datasource/rubygems/metadata-cache', () => {
   const cache: Map<string, unknown> = new Map();
 
-  packageCache.get.mockImplementation(
-    (ns, key) => Promise.resolve(cache.get(`${ns}::${key}`)) as never
-  );
-
-  packageCache.set.mockImplementation((ns, key, value) => {
-    cache.set(`${ns}::${key}`, value);
-    return Promise.resolve() as never;
-  });
-
   beforeEach(() => {
     cache.clear();
+
+    packageCache.get.mockImplementation(
+      (ns, key) => Promise.resolve(cache.get(`${ns}::${key}`)) as never
+    );
+
+    packageCache.set.mockImplementation((ns, key, value) => {
+      cache.set(`${ns}::${key}`, value);
+      return Promise.resolve() as never;
+    });
   });
 
   it('fetches data', async () => {
diff --git a/lib/modules/manager/bazel-module/extract.spec.ts b/lib/modules/manager/bazel-module/extract.spec.ts
index 133b0f1e8c..96197b0f4b 100644
--- a/lib/modules/manager/bazel-module/extract.spec.ts
+++ b/lib/modules/manager/bazel-module/extract.spec.ts
@@ -16,10 +16,7 @@ describe('modules/manager/bazel-module/extract', () => {
   describe('extractPackageFile()', () => {
     beforeEach(() => {
       GlobalConfig.set(adminConfig);
-    });
-
-    afterEach(() => {
-      GlobalConfig.reset();
+      jest.restoreAllMocks();
     });
 
     it('returns null if fails to parse', async () => {
@@ -31,7 +28,7 @@ describe('modules/manager/bazel-module/extract', () => {
     });
 
     it('returns null if something throws an error', async () => {
-      jest.spyOn(parser, 'parse').mockImplementationOnce((input) => {
+      jest.spyOn(parser, 'parse').mockImplementationOnce(() => {
         throw new Error('Test error');
       });
       const result = await extractPackageFile('content', 'MODULE.bazel');
@@ -54,9 +51,9 @@ describe('modules/manager/bazel-module/extract', () => {
     it('returns bazel_dep and git_override dependencies', async () => {
       const input = codeBlock`
         bazel_dep(name = "rules_foo", version = "1.2.3")
-        
+
         bazel_dep(name = "rules_bar", version = "1.0.0", dev_dependency = True)
-        
+
         git_override(
             module_name = "rules_foo",
             commit = "850cb49c8649e463b80ef7984e7c744279746170",
diff --git a/lib/modules/manager/bundler/artifacts.spec.ts b/lib/modules/manager/bundler/artifacts.spec.ts
index f90b772d99..d4bbf4d8b8 100644
--- a/lib/modules/manager/bundler/artifacts.spec.ts
+++ b/lib/modules/manager/bundler/artifacts.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import { join } from 'upath';
 import {
   envMock,
@@ -23,10 +24,10 @@ const datasource = mocked(_datasource);
 const bundlerHostRules = mocked(_bundlerHostRules);
 
 jest.mock('../../../util/exec/env');
-jest.mock('../../datasource');
+jest.mock('../../datasource', () => mockDeep());
 jest.mock('../../../util/fs');
 jest.mock('../../../util/git');
-jest.mock('../../../util/host-rules');
+jest.mock('../../../util/host-rules', () => mockDeep());
 jest.mock('./host-rules');
 
 process.env.CONTAINERBASE = 'true';
@@ -52,7 +53,6 @@ const updatedGemfileLock = {
 describe('modules/manager/bundler/artifacts', () => {
   describe('updateArtifacts', () => {
     beforeEach(() => {
-      jest.resetAllMocks();
       jest.resetModules();
 
       delete process.env.GEM_HOME;
diff --git a/lib/modules/manager/cargo/artifacts.spec.ts b/lib/modules/manager/cargo/artifacts.spec.ts
index 5850ba51b3..f035d46a6e 100644
--- a/lib/modules/manager/cargo/artifacts.spec.ts
+++ b/lib/modules/manager/cargo/artifacts.spec.ts
@@ -26,9 +26,6 @@ const adminConfig: RepoGlobalConfig = {
 
 describe('modules/manager/cargo/artifacts', () => {
   beforeEach(() => {
-    jest.resetAllMocks();
-    jest.resetModules();
-
     env.getChildProcessEnv.mockReturnValue(envMock.basic);
     GlobalConfig.set(adminConfig);
     docker.resetPrefetchedImages();
diff --git a/lib/modules/manager/cocoapods/artifacts.spec.ts b/lib/modules/manager/cocoapods/artifacts.spec.ts
index 80d6e085ca..fcffceaccf 100644
--- a/lib/modules/manager/cocoapods/artifacts.spec.ts
+++ b/lib/modules/manager/cocoapods/artifacts.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import { join } from 'upath';
 import { envMock, mockExecAll } from '../../../../test/exec-util';
 import { env, fs, git, mocked, partial } from '../../../../test/util';
@@ -12,8 +13,7 @@ import { updateArtifacts } from '.';
 jest.mock('../../../util/exec/env');
 jest.mock('../../../util/git');
 jest.mock('../../../util/fs');
-jest.mock('../../platform');
-jest.mock('../../datasource');
+jest.mock('../../datasource', () => mockDeep());
 
 const datasource = mocked(_datasource);
 
@@ -31,7 +31,6 @@ const adminConfig: RepoGlobalConfig = {
 
 describe('modules/manager/cocoapods/artifacts', () => {
   beforeEach(() => {
-    jest.resetAllMocks();
     env.getChildProcessEnv.mockReturnValue(envMock.basic);
     jest.spyOn(docker, 'removeDockerContainer').mockResolvedValue();
     // can't be mocked
diff --git a/lib/modules/manager/composer/artifacts.spec.ts b/lib/modules/manager/composer/artifacts.spec.ts
index 7ad1a8bc21..29fa33a66f 100644
--- a/lib/modules/manager/composer/artifacts.spec.ts
+++ b/lib/modules/manager/composer/artifacts.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import { join } from 'upath';
 import { envMock, mockExecAll } from '../../../../test/exec-util';
 import { env, fs, git, mocked, partial } from '../../../../test/util';
@@ -13,7 +14,7 @@ import type { UpdateArtifactsConfig } from '../types';
 import * as composer from '.';
 
 jest.mock('../../../util/exec/env');
-jest.mock('../../datasource');
+jest.mock('../../datasource', () => mockDeep());
 jest.mock('../../../util/fs');
 jest.mock('../../../util/git');
 
@@ -44,8 +45,6 @@ const repoStatus = partial<StatusResult>({
 
 describe('modules/manager/composer/artifacts', () => {
   beforeEach(() => {
-    jest.resetAllMocks();
-    jest.resetModules();
     env.getChildProcessEnv.mockReturnValue(envMock.basic);
     docker.resetPrefetchedImages();
     hostRules.clear();
diff --git a/lib/modules/manager/composer/utils.spec.ts b/lib/modules/manager/composer/utils.spec.ts
index 7078bc6356..46abbf0fcc 100644
--- a/lib/modules/manager/composer/utils.spec.ts
+++ b/lib/modules/manager/composer/utils.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import { GlobalConfig } from '../../../config/global';
 import * as hostRules from '../../../util/host-rules';
 import { Lockfile, PackageFile } from './schema';
@@ -7,7 +8,7 @@ import {
   requireComposerDependencyInstallation,
 } from './utils';
 
-jest.mock('../../datasource');
+jest.mock('../../datasource', () => mockDeep());
 
 describe('modules/manager/composer/utils', () => {
   beforeEach(() => {
diff --git a/lib/modules/manager/git-submodules/extract.spec.ts b/lib/modules/manager/git-submodules/extract.spec.ts
index 6e756d0c0a..42f4a289a2 100644
--- a/lib/modules/manager/git-submodules/extract.spec.ts
+++ b/lib/modules/manager/git-submodules/extract.spec.ts
@@ -7,8 +7,7 @@ import { extractPackageFile } from '.';
 
 jest.mock('simple-git');
 const simpleGitFactoryMock = simpleGit as jest.Mock<Partial<SimpleGit>>;
-// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
-const Git = jest.requireActual('simple-git') as SimpleGitFactory;
+const Git = jest.requireActual<SimpleGitFactory>('simple-git');
 
 const gitMock = mock<SimpleGit>();
 
diff --git a/lib/modules/manager/gomod/artifacts.spec.ts b/lib/modules/manager/gomod/artifacts.spec.ts
index 9dfbf2f1f0..9e09f9c6ab 100644
--- a/lib/modules/manager/gomod/artifacts.spec.ts
+++ b/lib/modules/manager/gomod/artifacts.spec.ts
@@ -1,4 +1,5 @@
 import { codeBlock } from 'common-tags';
+import { mockDeep } from 'jest-mock-extended';
 import { join } from 'upath';
 import { envMock, mockExecAll } from '../../../../test/exec-util';
 import { env, fs, git, mocked, partial } from '../../../../test/util';
@@ -11,22 +12,22 @@ import * as _datasource from '../../datasource';
 import type { UpdateArtifactsConfig } from '../types';
 import * as gomod from '.';
 
+type FS = typeof import('../../../util/fs');
+
 jest.mock('../../../util/exec/env');
 jest.mock('../../../util/git');
-jest.mock('../../../util/host-rules');
+jest.mock('../../../util/host-rules', () => mockDeep());
 jest.mock('../../../util/http');
 jest.mock('../../../util/fs', () => {
   // restore
   return {
     __esModules: true,
-    // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
-    ...(jest.createMockFromModule('../../../util/fs') as any),
-    // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
-    isValidLocalPath: (jest.requireActual('../../../util/fs') as any)
-      .isValidLocalPath,
+    ...jest.createMockFromModule<FS>('../../../util/fs'),
+    isValidLocalPath:
+      jest.requireActual<FS>('../../../util/fs').isValidLocalPath,
   };
 });
-jest.mock('../../datasource');
+jest.mock('../../datasource', () => mockDeep());
 
 process.env.CONTAINERBASE = 'true';
 
@@ -78,9 +79,6 @@ const goEnv = {
 
 describe('modules/manager/gomod/artifacts', () => {
   beforeEach(() => {
-    jest.resetAllMocks();
-    jest.resetModules();
-
     delete process.env.GOPATH;
     env.getChildProcessEnv.mockReturnValue({ ...envMock.basic, ...goEnv });
     GlobalConfig.set(adminConfig);
diff --git a/lib/modules/manager/gradle-wrapper/artifacts.spec.ts b/lib/modules/manager/gradle-wrapper/artifacts.spec.ts
index 4f4ec1028a..039dcb7fb8 100644
--- a/lib/modules/manager/gradle-wrapper/artifacts.spec.ts
+++ b/lib/modules/manager/gradle-wrapper/artifacts.spec.ts
@@ -1,5 +1,6 @@
 import type { Stats } from 'node:fs';
 import os from 'node:os';
+import { mockDeep } from 'jest-mock-extended';
 import { join } from 'upath';
 import { envMock, mockExecAll } from '../../../../test/exec-util';
 import { Fixtures } from '../../../../test/fixtures';
@@ -25,7 +26,7 @@ import { updateArtifacts } from '.';
 jest.mock('../../../util/fs');
 jest.mock('../../../util/git');
 jest.mock('../../../util/exec/env');
-jest.mock('../../datasource');
+jest.mock('../../datasource', () => mockDeep());
 jest.mock('../gradle');
 
 process.env.CONTAINERBASE = 'true';
diff --git a/lib/modules/manager/gradle/artifacts.spec.ts b/lib/modules/manager/gradle/artifacts.spec.ts
index 6cf4420d51..b8ed96d825 100644
--- a/lib/modules/manager/gradle/artifacts.spec.ts
+++ b/lib/modules/manager/gradle/artifacts.spec.ts
@@ -1,4 +1,5 @@
 import os from 'node:os';
+import { mockDeep } from 'jest-mock-extended';
 import { join } from 'upath';
 import {
   envMock,
@@ -26,7 +27,7 @@ import { updateArtifacts } from '.';
 jest.mock('../../../util/fs');
 jest.mock('../../../util/git');
 jest.mock('../../../util/exec/env');
-jest.mock('../../datasource');
+jest.mock('../../datasource', () => mockDeep());
 
 process.env.CONTAINERBASE = 'true';
 
diff --git a/lib/modules/manager/gradle/extract.spec.ts b/lib/modules/manager/gradle/extract.spec.ts
index d007dd7ff3..b6ad592650 100644
--- a/lib/modules/manager/gradle/extract.spec.ts
+++ b/lib/modules/manager/gradle/extract.spec.ts
@@ -28,8 +28,8 @@ function mockFs(files: Record<string, string>): void {
 }
 
 describe('modules/manager/gradle/extract', () => {
-  afterAll(() => {
-    jest.resetAllMocks();
+  beforeEach(() => {
+    jest.restoreAllMocks();
   });
 
   it('returns null', async () => {
diff --git a/lib/modules/manager/gradle/extract/consistent-versions-plugin.spec.ts b/lib/modules/manager/gradle/extract/consistent-versions-plugin.spec.ts
index 4598295f8a..c5e89a4dd9 100644
--- a/lib/modules/manager/gradle/extract/consistent-versions-plugin.spec.ts
+++ b/lib/modules/manager/gradle/extract/consistent-versions-plugin.spec.ts
@@ -6,10 +6,6 @@ import {
 } from './consistent-versions-plugin';
 
 describe('modules/manager/gradle/extract/consistent-versions-plugin', () => {
-  afterAll(() => {
-    jest.resetAllMocks();
-  });
-
   it('gradle-consistent-versions plugin works for sub folders', () => {
     const fsMock = {
       'mysub/build.gradle.kts': `(this file contains) 'com.palantir.consistent-versions'`,
diff --git a/lib/modules/manager/helm-requirements/extract.spec.ts b/lib/modules/manager/helm-requirements/extract.spec.ts
index ebb9748a19..e203872bdd 100644
--- a/lib/modules/manager/helm-requirements/extract.spec.ts
+++ b/lib/modules/manager/helm-requirements/extract.spec.ts
@@ -5,11 +5,6 @@ jest.mock('../../../util/fs');
 
 describe('modules/manager/helm-requirements/extract', () => {
   describe('extractPackageFile()', () => {
-    beforeEach(() => {
-      jest.resetAllMocks();
-      fs.readLocalFile = jest.fn();
-    });
-
     it('ensure that currentValue is string', () => {
       fs.readLocalFile.mockResolvedValueOnce(`
       apiVersion: v1
diff --git a/lib/modules/manager/helm-values/extract.spec.ts b/lib/modules/manager/helm-values/extract.spec.ts
index 9798984a88..3666b84413 100644
--- a/lib/modules/manager/helm-values/extract.spec.ts
+++ b/lib/modules/manager/helm-values/extract.spec.ts
@@ -11,10 +11,6 @@ const helmMultiAndNestedImageValues = Fixtures.get(
 
 describe('modules/manager/helm-values/extract', () => {
   describe('extractPackageFile()', () => {
-    beforeEach(() => {
-      jest.resetAllMocks();
-    });
-
     it('returns null for invalid yaml file content', () => {
       const result = extractPackageFile('nothing here: [');
       expect(result).toBeNull();
diff --git a/lib/modules/manager/helmfile/artifacts.spec.ts b/lib/modules/manager/helmfile/artifacts.spec.ts
index 10eaa9fd7d..a64c46e68f 100644
--- a/lib/modules/manager/helmfile/artifacts.spec.ts
+++ b/lib/modules/manager/helmfile/artifacts.spec.ts
@@ -1,4 +1,5 @@
 import { codeBlock } from 'common-tags';
+import { mockDeep } from 'jest-mock-extended';
 import { join } from 'upath';
 import { envMock, mockExecAll } from '../../../../test/exec-util';
 import { env, fs, git, mocked } from '../../../../test/util';
@@ -10,7 +11,7 @@ import * as _datasource from '../../datasource';
 import type { UpdateArtifactsConfig } from '../types';
 import * as helmfile from '.';
 
-jest.mock('../../datasource');
+jest.mock('../../datasource', () => mockDeep());
 jest.mock('../../../util/exec/env');
 jest.mock('../../../util/http');
 jest.mock('../../../util/fs');
diff --git a/lib/modules/manager/helmfile/extract.spec.ts b/lib/modules/manager/helmfile/extract.spec.ts
index 10f9281a33..891ad097aa 100644
--- a/lib/modules/manager/helmfile/extract.spec.ts
+++ b/lib/modules/manager/helmfile/extract.spec.ts
@@ -12,7 +12,6 @@ describe('modules/manager/helmfile/extract', () => {
   describe('extractPackageFile()', () => {
     beforeEach(() => {
       GlobalConfig.set({ localDir });
-      jest.resetAllMocks();
     });
 
     it('returns null if no releases', async () => {
diff --git a/lib/modules/manager/helmv3/artifacts.spec.ts b/lib/modules/manager/helmv3/artifacts.spec.ts
index ff8e5b3ee9..a0166b1a2b 100644
--- a/lib/modules/manager/helmv3/artifacts.spec.ts
+++ b/lib/modules/manager/helmv3/artifacts.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import { join } from 'upath';
 import { envMock, mockExecAll } from '../../../../test/exec-util';
 import { Fixtures } from '../../../../test/fixtures';
@@ -11,7 +12,7 @@ import * as _datasource from '../../datasource';
 import type { UpdateArtifactsConfig } from '../types';
 import * as helmv3 from '.';
 
-jest.mock('../../datasource');
+jest.mock('../../datasource', () => mockDeep());
 jest.mock('../../../util/exec/env');
 jest.mock('../../../util/http');
 jest.mock('../../../util/fs');
@@ -36,9 +37,6 @@ const chartFileAlias = Fixtures.get('ChartAlias.yaml');
 
 describe('modules/manager/helmv3/artifacts', () => {
   beforeEach(() => {
-    jest.resetAllMocks();
-    jest.resetModules();
-
     env.getChildProcessEnv.mockReturnValue(envMock.basic);
     GlobalConfig.set(adminConfig);
     docker.resetPrefetchedImages();
diff --git a/lib/modules/manager/helmv3/extract.spec.ts b/lib/modules/manager/helmv3/extract.spec.ts
index eb0d004177..916cd2ba54 100644
--- a/lib/modules/manager/helmv3/extract.spec.ts
+++ b/lib/modules/manager/helmv3/extract.spec.ts
@@ -12,11 +12,6 @@ const config = partial<ExtractConfig>({
 
 describe('modules/manager/helmv3/extract', () => {
   describe('extractPackageFile()', () => {
-    beforeEach(() => {
-      jest.resetAllMocks();
-      fs.readLocalFile = jest.fn();
-    });
-
     it('skips invalid registry urls', async () => {
       const content = `
       apiVersion: v2
diff --git a/lib/modules/manager/homebrew/update.spec.ts b/lib/modules/manager/homebrew/update.spec.ts
index 013f4fa4c4..c57a28858a 100644
--- a/lib/modules/manager/homebrew/update.spec.ts
+++ b/lib/modules/manager/homebrew/update.spec.ts
@@ -9,11 +9,6 @@ const ibazel = Fixtures.get('ibazel.rb');
 const baseUrl = 'https://github.com';
 
 describe('modules/manager/homebrew/update', () => {
-  beforeEach(() => {
-    jest.resetAllMocks();
-    jest.resetModules();
-  });
-
   it('updates "releases" github dependency', async () => {
     const upgrade = {
       currentValue: 'v0.16.1',
diff --git a/lib/modules/manager/maven-wrapper/artifacts.spec.ts b/lib/modules/manager/maven-wrapper/artifacts.spec.ts
index 023249152b..06fa35f792 100644
--- a/lib/modules/manager/maven-wrapper/artifacts.spec.ts
+++ b/lib/modules/manager/maven-wrapper/artifacts.spec.ts
@@ -1,5 +1,6 @@
 import type { Stats } from 'node:fs';
 import os from 'node:os';
+import { mockDeep } from 'jest-mock-extended';
 import type { StatusResult } from 'simple-git';
 import { join } from 'upath';
 import { envMock, mockExecAll } from '../../../../test/exec-util';
@@ -12,7 +13,7 @@ import { updateArtifacts } from '.';
 jest.mock('../../../util/fs');
 jest.mock('../../../util/git');
 jest.mock('../../../util/exec/env');
-jest.mock('../../datasource');
+jest.mock('../../datasource', () => mockDeep());
 
 process.env.CONTAINERBASE = 'true';
 
diff --git a/lib/modules/manager/mix/artifacts.spec.ts b/lib/modules/manager/mix/artifacts.spec.ts
index 0f1b12dd4f..4115d20738 100644
--- a/lib/modules/manager/mix/artifacts.spec.ts
+++ b/lib/modules/manager/mix/artifacts.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import { join } from 'upath';
 import { envMock, mockExecAll } from '../../../../test/exec-util';
 import { env, fs, hostRules, mockedFunction } from '../../../../test/util';
@@ -10,8 +11,8 @@ import { updateArtifacts } from '.';
 
 jest.mock('../../../util/exec/env');
 jest.mock('../../../util/fs');
-jest.mock('../../../util/host-rules');
-jest.mock('../../datasource');
+jest.mock('../../../util/host-rules', () => mockDeep());
+jest.mock('../../datasource', () => mockDeep());
 
 const getPkgReleases = mockedFunction(_getPkgReleases);
 
@@ -29,8 +30,6 @@ const config: UpdateArtifactsConfig = {};
 
 describe('modules/manager/mix/artifacts', () => {
   beforeEach(() => {
-    jest.resetAllMocks();
-    jest.resetModules();
     hostRules.getAll.mockReturnValue([]);
 
     env.getChildProcessEnv.mockReturnValue(envMock.basic);
diff --git a/lib/modules/manager/nix/artifacts.spec.ts b/lib/modules/manager/nix/artifacts.spec.ts
index 779513f29c..9b58b41cc0 100644
--- a/lib/modules/manager/nix/artifacts.spec.ts
+++ b/lib/modules/manager/nix/artifacts.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import type { StatusResult } from 'simple-git';
 import { join } from 'upath';
 import {
@@ -16,7 +17,7 @@ import { updateArtifacts } from '.';
 jest.mock('../../../util/exec/env');
 jest.mock('../../../util/fs');
 jest.mock('../../../util/git');
-jest.mock('../../../util/host-rules');
+jest.mock('../../../util/host-rules', () => mockDeep());
 
 const adminConfig: RepoGlobalConfig = {
   // `join` fixes Windows CI
@@ -52,7 +53,6 @@ describe('modules/manager/nix/artifacts', () => {
   const hostRules = mocked(_hostRules);
 
   beforeEach(() => {
-    jest.resetAllMocks();
     env.getChildProcessEnv.mockReturnValue({
       ...envMock.basic,
       LANG: 'en_US.UTF-8',
diff --git a/lib/modules/manager/npm/extract/index.spec.ts b/lib/modules/manager/npm/extract/index.spec.ts
index f9c34b2c4a..bf32d35cee 100644
--- a/lib/modules/manager/npm/extract/index.spec.ts
+++ b/lib/modules/manager/npm/extract/index.spec.ts
@@ -5,9 +5,6 @@ import type { ExtractConfig } from '../../types';
 import * as npmExtract from '.';
 
 jest.mock('../../../../util/fs');
-const realFs = jest.requireActual<typeof import('../../../../util/fs')>(
-  '../../../../util/fs'
-);
 
 const defaultExtractConfig = {
   skipInstalls: null,
@@ -27,7 +24,7 @@ const invalidNameContent = Fixtures.get('invalid-name.json', '..');
 describe('modules/manager/npm/extract/index', () => {
   describe('.extractPackageFile()', () => {
     beforeEach(() => {
-      jest.resetAllMocks();
+      const realFs = jest.requireActual<typeof fs>('../../../../util/fs');
       fs.readLocalFile.mockResolvedValue(null);
       fs.localPathExists.mockResolvedValue(false);
       fs.getSiblingFileName.mockImplementation(realFs.getSiblingFileName);
diff --git a/lib/modules/manager/npm/extract/locked-versions.spec.ts b/lib/modules/manager/npm/extract/locked-versions.spec.ts
index c63a8494d8..8d4e8ce57c 100644
--- a/lib/modules/manager/npm/extract/locked-versions.spec.ts
+++ b/lib/modules/manager/npm/extract/locked-versions.spec.ts
@@ -12,7 +12,7 @@ const yarn = mocked(_yarn);
 
 jest.mock('./npm');
 jest.mock('./yarn', () => ({
-  ...jest.requireActual<any>('./yarn'),
+  ...jest.requireActual<typeof import('./yarn')>('./yarn'),
   getYarnLock: jest.fn(),
 }));
 jest.mock('./pnpm');
diff --git a/lib/modules/manager/npm/extract/pnpm.spec.ts b/lib/modules/manager/npm/extract/pnpm.spec.ts
index c44a66257c..26227db1b0 100644
--- a/lib/modules/manager/npm/extract/pnpm.spec.ts
+++ b/lib/modules/manager/npm/extract/pnpm.spec.ts
@@ -1,8 +1,10 @@
 import yaml from 'js-yaml';
 import { Fixtures } from '../../../../../test/fixtures';
-import { getFixturePath, logger } from '../../../../../test/util';
+import { getFixturePath, logger, partial } from '../../../../../test/util';
 import { GlobalConfig } from '../../../../config/global';
 import * as fs from '../../../../util/fs';
+import type { PackageFile } from '../../types';
+import type { NpmManagerData } from '../types';
 import {
   detectPnpmWorkspaces,
   extractPnpmFilters,
@@ -15,6 +17,10 @@ describe('modules/manager/npm/extract/pnpm', () => {
     GlobalConfig.set({ localDir: getFixturePath('pnpm-monorepo/', '..') });
   });
 
+  beforeEach(() => {
+    jest.restoreAllMocks();
+  });
+
   describe('.extractPnpmFilters()', () => {
     it('detects errors in pnpm-workspace.yml file structure', async () => {
       jest
@@ -66,6 +72,9 @@ describe('modules/manager/npm/extract/pnpm', () => {
     });
 
     it('detects missing pnpm-lock.yaml when pnpm-workspace.yaml was already found', async () => {
+      jest
+        .spyOn(fs, 'findLocalSiblingOrParent')
+        .mockResolvedValueOnce('pnpm-workspace.yaml');
       jest.spyOn(fs, 'localPathExists').mockResolvedValueOnce(false);
 
       const packageFile = 'package.json';
@@ -83,7 +92,7 @@ describe('modules/manager/npm/extract/pnpm', () => {
 
   describe('.detectPnpmWorkspaces()', () => {
     it('uses pnpm workspaces', async () => {
-      const packageFiles = [
+      const packageFiles = partial<PackageFile<NpmManagerData>>([
         {
           packageFile: 'package.json',
           managerData: { pnpmShrinkwrap: 'pnpm-lock.yaml' },
@@ -91,80 +100,80 @@ describe('modules/manager/npm/extract/pnpm', () => {
         {
           packageFile: 'nested-packages/group/a/package.json',
           managerData: {
-            pnpmShrinkwrap: undefined as undefined | string,
+            pnpmShrinkwrap: undefined,
             packageJsonName: '@demo/nested-group-a',
           },
         },
         {
           packageFile: 'nested-packages/group/b/package.json',
           managerData: {
-            pnpmShrinkwrap: undefined as undefined | string,
+            pnpmShrinkwrap: undefined,
             packageJsonName: '@demo/nested-group-b',
           },
         },
         {
           packageFile: 'non-nested-packages/a/package.json',
           managerData: {
-            pnpmShrinkwrap: undefined as undefined | string,
+            pnpmShrinkwrap: undefined,
             packageJsonName: '@demo/non-nested-a',
           },
         },
         {
           packageFile: 'non-nested-packages/b/package.json',
           managerData: {
-            pnpmShrinkwrap: undefined as undefined | string,
+            pnpmShrinkwrap: undefined,
             packageJsonName: '@demo/non-nested-b',
           },
         },
         {
           packageFile: 'solo-package/package.json',
           managerData: {
-            pnpmShrinkwrap: undefined as undefined | string,
+            pnpmShrinkwrap: undefined,
             packageJsonName: '@demo/solo',
           },
         },
         {
           packageFile: 'solo-package-leading-dot-slash/package.json',
           managerData: {
-            pnpmShrinkwrap: undefined as undefined | string,
+            pnpmShrinkwrap: undefined,
             packageJsonName: '@demo/solo-leading-dot-slash',
           },
         },
         {
           packageFile: 'solo-package-leading-double-dot-slash/package.json',
           managerData: {
-            pnpmShrinkwrap: undefined as undefined | string,
+            pnpmShrinkwrap: undefined,
             packageJsonName: '@demo/solo-leading-double-dot-slash',
           },
         },
         {
           packageFile: 'solo-package-trailing-slash/package.json',
           managerData: {
-            pnpmShrinkwrap: undefined as undefined | string,
+            pnpmShrinkwrap: undefined,
             packageJsonName: '@demo/solo-trailing-slash',
           },
         },
         {
           packageFile: 'test/test-package/package.json',
           managerData: {
-            pnpmShrinkwrap: undefined as undefined | string,
+            pnpmShrinkwrap: undefined,
             packageJsonName: '@demo/test-package',
           },
         },
         {
           packageFile: 'tests/test-package2/package.json',
           managerData: {
-            pnpmShrinkwrap: undefined as undefined | string,
+            pnpmShrinkwrap: undefined,
             packageJsonName: '@demo/test-package2',
           },
         },
-      ];
+      ]);
 
       await detectPnpmWorkspaces(packageFiles);
       expect(packageFiles).toMatchSnapshot();
       expect(
         packageFiles.every(
-          (packageFile) => packageFile.managerData.pnpmShrinkwrap
+          (packageFile) => packageFile.managerData?.pnpmShrinkwrap !== undefined
         )
       ).toBeTrue();
     });
@@ -195,12 +204,12 @@ describe('modules/manager/npm/extract/pnpm', () => {
         {
           packageFile: 'nested-packages/group/a/package.json',
           packageJsonName: '@demo/nested-group-a',
-          managerData: { pnpmShrinkwrap: undefined as undefined | string },
+          managerData: { pnpmShrinkwrap: undefined },
         },
         {
           packageFile: 'not-matching/b/package.json',
           packageJsonName: '@not-matching/b',
-          managerData: { pnpmShrinkwrap: undefined as undefined | string },
+          managerData: { pnpmShrinkwrap: undefined },
         },
       ];
 
@@ -231,17 +240,15 @@ describe('modules/manager/npm/extract/pnpm', () => {
   });
 
   describe('.getPnpmLock()', () => {
-    const readLocalFile = jest.spyOn(fs, 'readLocalFile');
-
     it('returns empty if failed to parse', async () => {
-      readLocalFile.mockResolvedValueOnce(undefined as never);
+      jest.spyOn(fs, 'readLocalFile').mockResolvedValueOnce(undefined as never);
       const res = await getPnpmLock('package.json');
       expect(res.lockedVersionsWithPath).toBeUndefined();
     });
 
     it('extracts version from monorepo', async () => {
       const plocktest1Lock = Fixtures.get('pnpm-monorepo/pnpm-lock.yaml', '..');
-      readLocalFile.mockResolvedValueOnce(plocktest1Lock);
+      jest.spyOn(fs, 'readLocalFile').mockResolvedValueOnce(plocktest1Lock);
       const res = await getPnpmLock('package.json');
       expect(Object.keys(res.lockedVersionsWithPath!)).toHaveLength(11);
     });
@@ -251,13 +258,13 @@ describe('modules/manager/npm/extract/pnpm', () => {
         'lockfile-parsing/pnpm-lock.yaml',
         '..'
       );
-      readLocalFile.mockResolvedValueOnce(plocktest1Lock);
+      jest.spyOn(fs, 'readLocalFile').mockResolvedValueOnce(plocktest1Lock);
       const res = await getPnpmLock('package.json');
       expect(Object.keys(res.lockedVersionsWithPath!)).toHaveLength(1);
     });
 
     it('returns empty if no deps', async () => {
-      readLocalFile.mockResolvedValueOnce('{}');
+      jest.spyOn(fs, 'readLocalFile').mockResolvedValueOnce('{}');
       const res = await getPnpmLock('package.json');
       expect(res.lockedVersionsWithPath).toBeUndefined();
     });
diff --git a/lib/modules/manager/npm/post-update/__snapshots__/yarn.spec.ts.snap b/lib/modules/manager/npm/post-update/__snapshots__/yarn.spec.ts.snap
index 98f903a0ce..dd9dccc6e9 100644
--- a/lib/modules/manager/npm/post-update/__snapshots__/yarn.spec.ts.snap
+++ b/lib/modules/manager/npm/post-update/__snapshots__/yarn.spec.ts.snap
@@ -9,13 +9,6 @@ exports[`modules/manager/npm/post-update/yarn allows and ignore scripts 1`] = `
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_HTTP_TIMEOUT": "100000",
@@ -36,13 +29,6 @@ exports[`modules/manager/npm/post-update/yarn catches errors 1`] = `
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
       },
       "maxBuffer": 10485760,
       "timeout": 900000,
@@ -60,13 +46,6 @@ exports[`modules/manager/npm/post-update/yarn does not use global cache if zero
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_ENABLE_SCRIPTS": "0",
         "YARN_HTTP_TIMEOUT": "100000",
@@ -87,13 +66,6 @@ exports[`modules/manager/npm/post-update/yarn generates lock files using yarn v1
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_CACHE_FOLDER": "/tmp/renovate/cache/yarn",
       },
       "maxBuffer": 10485760,
@@ -107,13 +79,6 @@ exports[`modules/manager/npm/post-update/yarn generates lock files using yarn v1
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_CACHE_FOLDER": "/tmp/renovate/cache/yarn",
       },
       "maxBuffer": 10485760,
@@ -127,13 +92,6 @@ exports[`modules/manager/npm/post-update/yarn generates lock files using yarn v1
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_CACHE_FOLDER": "/tmp/renovate/cache/yarn",
       },
       "maxBuffer": 10485760,
@@ -147,13 +105,6 @@ exports[`modules/manager/npm/post-update/yarn generates lock files using yarn v1
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_CACHE_FOLDER": "/tmp/renovate/cache/yarn",
       },
       "maxBuffer": 10485760,
@@ -167,13 +118,6 @@ exports[`modules/manager/npm/post-update/yarn generates lock files using yarn v1
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_CACHE_FOLDER": "/tmp/renovate/cache/yarn",
       },
       "maxBuffer": 10485760,
@@ -192,13 +136,6 @@ exports[`modules/manager/npm/post-update/yarn generates lock files using yarn v2
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_ENABLE_SCRIPTS": "0",
@@ -221,13 +158,6 @@ exports[`modules/manager/npm/post-update/yarn generates lock files using yarn v2
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_ENABLE_SCRIPTS": "0",
@@ -245,13 +175,6 @@ exports[`modules/manager/npm/post-update/yarn generates lock files using yarn v2
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_ENABLE_SCRIPTS": "0",
@@ -274,13 +197,6 @@ exports[`modules/manager/npm/post-update/yarn generates lock files using yarn v3
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_GLOBAL_FOLDER": "/tmp/renovate/cache/berry",
@@ -297,13 +213,6 @@ exports[`modules/manager/npm/post-update/yarn generates lock files using yarn v3
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_GLOBAL_FOLDER": "/tmp/renovate/cache/berry",
@@ -325,13 +234,6 @@ exports[`modules/manager/npm/post-update/yarn only skips build if skipInstalls i
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_HTTP_TIMEOUT": "100000",
@@ -347,13 +249,6 @@ exports[`modules/manager/npm/post-update/yarn only skips build if skipInstalls i
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_HTTP_TIMEOUT": "100000",
@@ -374,13 +269,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file maintenance in
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
       },
       "maxBuffer": 10485760,
       "timeout": 900000,
@@ -393,13 +281,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file maintenance in
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
       },
       "maxBuffer": 10485760,
       "timeout": 900000,
@@ -412,13 +293,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file maintenance in
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
       },
       "maxBuffer": 10485760,
       "timeout": 900000,
@@ -431,13 +305,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file maintenance in
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
       },
       "maxBuffer": 10485760,
       "timeout": 900000,
@@ -450,13 +317,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file maintenance in
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
       },
       "maxBuffer": 10485760,
       "timeout": 900000,
@@ -474,13 +334,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file maintenance in
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_ENABLE_SCRIPTS": "0",
@@ -502,13 +355,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file maintenance in
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_ENABLE_SCRIPTS": "0",
@@ -525,13 +371,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file maintenance in
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_ENABLE_SCRIPTS": "0",
@@ -553,13 +392,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file maintenance in
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_HTTP_TIMEOUT": "100000",
@@ -575,13 +407,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file maintenance in
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_HTTP_TIMEOUT": "100000",
@@ -602,13 +427,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file maintenance usi
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
       },
       "maxBuffer": 10485760,
       "timeout": 900000,
@@ -621,13 +439,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file maintenance usi
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
       },
       "maxBuffer": 10485760,
       "timeout": 900000,
@@ -640,13 +451,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file maintenance usi
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
       },
       "maxBuffer": 10485760,
       "timeout": 900000,
@@ -659,13 +463,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file maintenance usi
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
       },
       "maxBuffer": 10485760,
       "timeout": 900000,
@@ -678,13 +475,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file maintenance usi
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
       },
       "maxBuffer": 10485760,
       "timeout": 900000,
@@ -702,13 +492,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file maintenance usi
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_ENABLE_SCRIPTS": "0",
@@ -730,13 +513,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file maintenance usi
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_ENABLE_SCRIPTS": "0",
@@ -753,13 +529,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file maintenance usi
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_ENABLE_SCRIPTS": "0",
@@ -781,13 +550,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file updates and ful
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
       },
       "maxBuffer": 10485760,
       "timeout": 900000,
@@ -800,13 +562,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file updates and ful
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
       },
       "maxBuffer": 10485760,
       "timeout": 900000,
@@ -824,13 +579,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file updates using y
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
       },
       "maxBuffer": 10485760,
       "timeout": 900000,
@@ -843,13 +591,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file updates using y
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
       },
       "maxBuffer": 10485760,
       "timeout": 900000,
@@ -867,13 +608,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file updates using y
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_ENABLE_SCRIPTS": "0",
@@ -890,13 +624,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file updates using y
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_ENABLE_SCRIPTS": "0",
@@ -918,13 +645,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file updates using y
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_HTTP_TIMEOUT": "100000",
@@ -940,13 +660,6 @@ exports[`modules/manager/npm/post-update/yarn performs lock file updates using y
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_HTTP_TIMEOUT": "100000",
@@ -967,13 +680,6 @@ exports[`modules/manager/npm/post-update/yarn performs yarn binary update using
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_HTTP_TIMEOUT": "100000",
@@ -989,13 +695,6 @@ exports[`modules/manager/npm/post-update/yarn performs yarn binary update using
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_HTTP_TIMEOUT": "100000",
@@ -1016,13 +715,6 @@ exports[`modules/manager/npm/post-update/yarn performs yarn binary update using
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_HTTP_TIMEOUT": "100000",
@@ -1038,13 +730,6 @@ exports[`modules/manager/npm/post-update/yarn performs yarn binary update using
       "encoding": "utf-8",
       "env": {
         "CI": "true",
-        "HOME": "/home/user",
-        "HTTPS_PROXY": "https://example.com",
-        "HTTP_PROXY": "http://example.com",
-        "LANG": "en_US.UTF-8",
-        "LC_ALL": "en_US",
-        "NO_PROXY": "localhost",
-        "PATH": "/tmp/path",
         "YARN_ENABLE_GLOBAL_CACHE": "1",
         "YARN_ENABLE_IMMUTABLE_INSTALLS": "false",
         "YARN_HTTP_TIMEOUT": "100000",
diff --git a/lib/modules/manager/npm/post-update/index.spec.ts b/lib/modules/manager/npm/post-update/index.spec.ts
index 3f28dbbfe8..e6fd13d849 100644
--- a/lib/modules/manager/npm/post-update/index.spec.ts
+++ b/lib/modules/manager/npm/post-update/index.spec.ts
@@ -62,7 +62,6 @@ describe('modules/manager/npm/post-update/index', () => {
   };
 
   beforeEach(() => {
-    jest.resetAllMocks();
     GlobalConfig.set({ localDir: '' });
     baseConfig = partial<PostUpdateConfig>({
       upgrades: [],
diff --git a/lib/modules/manager/npm/post-update/lerna.spec.ts b/lib/modules/manager/npm/post-update/lerna.spec.ts
index 8115050c2a..f81d5e5354 100644
--- a/lib/modules/manager/npm/post-update/lerna.spec.ts
+++ b/lib/modules/manager/npm/post-update/lerna.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import { envMock, mockExecAll } from '../../../../../test/exec-util';
 import { env, fs, mockedFunction, partial } from '../../../../../test/util';
 import { GlobalConfig } from '../../../../config/global';
@@ -9,7 +10,7 @@ import { getNodeToolConstraint } from './node-version';
 jest.mock('../../../../util/exec/env');
 jest.mock('../../../../util/fs');
 jest.mock('./node-version');
-jest.mock('../../../datasource');
+jest.mock('../../../datasource', () => mockDeep());
 
 process.env.CONTAINERBASE = 'true';
 
@@ -29,8 +30,6 @@ describe('modules/manager/npm/post-update/lerna', () => {
 
   describe('generateLockFiles()', () => {
     beforeEach(() => {
-      jest.resetAllMocks();
-      jest.resetModules();
       env.getChildProcessEnv.mockReturnValue(envMock.basic);
       GlobalConfig.set(globalConfig);
       mockedFunction(getNodeToolConstraint).mockResolvedValueOnce({
diff --git a/lib/modules/manager/npm/post-update/npm.spec.ts b/lib/modules/manager/npm/post-update/npm.spec.ts
index a282620ebe..ffa0273a2a 100644
--- a/lib/modules/manager/npm/post-update/npm.spec.ts
+++ b/lib/modules/manager/npm/post-update/npm.spec.ts
@@ -14,8 +14,6 @@ process.env.CONTAINERBASE = 'true';
 
 describe('modules/manager/npm/post-update/npm', () => {
   beforeEach(() => {
-    jest.resetAllMocks();
-    jest.resetModules();
     env.getChildProcessEnv.mockReturnValue(envMock.basic);
     GlobalConfig.set({ localDir: '' });
     mockedFunction(getNodeToolConstraint).mockResolvedValueOnce({
diff --git a/lib/modules/manager/npm/post-update/pnpm.spec.ts b/lib/modules/manager/npm/post-update/pnpm.spec.ts
index adf740f280..064af1bdae 100644
--- a/lib/modules/manager/npm/post-update/pnpm.spec.ts
+++ b/lib/modules/manager/npm/post-update/pnpm.spec.ts
@@ -17,7 +17,6 @@ describe('modules/manager/npm/post-update/pnpm', () => {
   let config: PostUpdateConfig;
 
   beforeEach(() => {
-    jest.resetAllMocks();
     config = partial<PostUpdateConfig>({ constraints: { pnpm: '^2.0.0' } });
     env.getChildProcessEnv.mockReturnValue(envMock.basic);
     GlobalConfig.set({ localDir: '' });
diff --git a/lib/modules/manager/npm/post-update/yarn.spec.ts b/lib/modules/manager/npm/post-update/yarn.spec.ts
index 01f25c822a..fb96a054f4 100644
--- a/lib/modules/manager/npm/post-update/yarn.spec.ts
+++ b/lib/modules/manager/npm/post-update/yarn.spec.ts
@@ -1,4 +1,5 @@
 import fs from 'fs-extra';
+import { mockDeep } from 'jest-mock-extended';
 import {
   ExecSnapshots,
   envMock,
@@ -16,11 +17,15 @@ import { getNodeToolConstraint } from './node-version';
 import * as yarnHelper from './yarn';
 
 jest.mock('fs-extra', () =>
-  require('../../../../../test/fixtures').Fixtures.fsExtra()
+  jest
+    .requireActual<typeof import('../../../../../test/fixtures')>(
+      '../../../../../test/fixtures'
+    )
+    .fsExtra()
 );
 jest.mock('../../../../util/exec/env');
 jest.mock('./node-version');
-jest.mock('../../../datasource');
+jest.mock('../../../datasource', () => mockDeep());
 
 delete process.env.NPM_CONFIG_CACHE;
 
@@ -34,14 +39,16 @@ const fixSnapshots = (snapshots: ExecSnapshots): ExecSnapshots =>
 const plocktest1PackageJson = Fixtures.get('plocktest1/package.json', '..');
 const plocktest1YarnLockV1 = Fixtures.get('plocktest1/yarn.lock', '..');
 
-jest.spyOn(docker, 'removeDockerContainer').mockResolvedValue();
 env.getChildProcessEnv.mockReturnValue(envMock.basic);
 
 describe('modules/manager/npm/post-update/yarn', () => {
+  const removeDockerContainer = jest.spyOn(docker, 'removeDockerContainer');
+
   beforeEach(() => {
     delete process.env.BUILDPACK;
     Fixtures.reset();
     GlobalConfig.set({ localDir: '.', cacheDir: '/tmp/cache' });
+    removeDockerContainer.mockResolvedValue();
     docker.resetPrefetchedImages();
     mockedFunction(getNodeToolConstraint).mockResolvedValueOnce({
       toolName: 'node',
diff --git a/lib/modules/manager/npm/update/package-version/index.spec.ts b/lib/modules/manager/npm/update/package-version/index.spec.ts
index 53829adc47..e40b5fb148 100644
--- a/lib/modules/manager/npm/update/package-version/index.spec.ts
+++ b/lib/modules/manager/npm/update/package-version/index.spec.ts
@@ -57,7 +57,7 @@ describe('modules/manager/npm/update/package-version/index', () => {
     });
 
     it('returns content if bumping errors', async () => {
-      jest.mock('semver', () => ({
+      jest.doMock('semver', () => ({
         inc: () => {
           throw new Error('semver inc');
         },
diff --git a/lib/modules/manager/nuget/artifacts.spec.ts b/lib/modules/manager/nuget/artifacts.spec.ts
index 9d72b820fc..a0fbeb9f30 100644
--- a/lib/modules/manager/nuget/artifacts.spec.ts
+++ b/lib/modules/manager/nuget/artifacts.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import { join } from 'upath';
 import { envMock, mockExecAll } from '../../../../test/exec-util';
 import { env, fs, git, mocked, scm } from '../../../../test/util';
@@ -12,16 +13,13 @@ import * as nuget from '.';
 
 jest.mock('../../../util/exec/env');
 jest.mock('../../../util/fs');
-jest.mock('../../../util/host-rules');
+jest.mock('../../../util/host-rules', () => mockDeep());
 jest.mock('../../../util/git');
 jest.mock('./util');
 
 const { getConfiguredRegistries, getDefaultRegistries } = mocked(util);
 const hostRules = mocked(_hostRules);
 
-const realFs =
-  jest.requireActual<typeof import('../../../util/fs')>('../../../util/fs');
-
 process.env.CONTAINERBASE = 'true';
 
 const adminConfig: RepoGlobalConfig = {
@@ -35,8 +33,8 @@ const config: UpdateArtifactsConfig = {};
 
 describe('modules/manager/nuget/artifacts', () => {
   beforeEach(() => {
-    jest.resetAllMocks();
-    jest.resetModules();
+    const realFs =
+      jest.requireActual<typeof import('../../../util/fs')>('../../../util/fs');
     getDefaultRegistries.mockReturnValue([]);
     env.getChildProcessEnv.mockReturnValue(envMock.basic);
     fs.privateCacheDir.mockImplementation(realFs.privateCacheDir);
diff --git a/lib/modules/manager/nuget/package-tree.spec.ts b/lib/modules/manager/nuget/package-tree.spec.ts
index 3b9e99e04c..ab210f0247 100644
--- a/lib/modules/manager/nuget/package-tree.spec.ts
+++ b/lib/modules/manager/nuget/package-tree.spec.ts
@@ -7,7 +7,13 @@ import type { RepoGlobalConfig } from '../../../config/types';
 import { getDependentPackageFiles } from './package-tree';
 
 jest.mock('fs', () => memfs);
-jest.mock('fs-extra', () => Fixtures.fsExtra());
+jest.mock('fs-extra', () =>
+  jest
+    .requireActual<typeof import('../../../../test/fixtures')>(
+      '../../../../test/fixtures'
+    )
+    .fsExtra()
+);
 jest.mock('../../../util/git');
 
 const adminConfig: RepoGlobalConfig = {
diff --git a/lib/modules/manager/pep621/artifacts.spec.ts b/lib/modules/manager/pep621/artifacts.spec.ts
index a5b8fcd55a..c3c3b9bd1b 100644
--- a/lib/modules/manager/pep621/artifacts.spec.ts
+++ b/lib/modules/manager/pep621/artifacts.spec.ts
@@ -1,4 +1,5 @@
 import { codeBlock } from 'common-tags';
+import { mockDeep } from 'jest-mock-extended';
 import { join } from 'upath';
 import { mockExecAll } from '../../../../test/exec-util';
 import { fs, mockedFunction } from '../../../../test/util';
@@ -9,7 +10,7 @@ import type { UpdateArtifactsConfig } from '../types';
 import { updateArtifacts } from './artifacts';
 
 jest.mock('../../../util/fs');
-jest.mock('../../datasource');
+jest.mock('../../datasource', () => mockDeep());
 
 const getPkgReleases = mockedFunction(_getPkgReleases);
 
diff --git a/lib/modules/manager/pip-compile/artifacts.spec.ts b/lib/modules/manager/pip-compile/artifacts.spec.ts
index a9fc034e84..350a88030d 100644
--- a/lib/modules/manager/pip-compile/artifacts.spec.ts
+++ b/lib/modules/manager/pip-compile/artifacts.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import { join } from 'upath';
 import { envMock, mockExecAll } from '../../../../test/exec-util';
 import { Fixtures } from '../../../../test/fixtures';
@@ -17,9 +18,9 @@ const datasource = mocked(_datasource);
 jest.mock('../../../util/exec/env');
 jest.mock('../../../util/fs');
 jest.mock('../../../util/git');
-jest.mock('../../../util/host-rules');
+jest.mock('../../../util/host-rules', () => mockDeep());
 jest.mock('../../../util/http');
-jest.mock('../../datasource');
+jest.mock('../../datasource', () => mockDeep());
 
 const adminConfig: RepoGlobalConfig = {
   // `join` fixes Windows CI
@@ -40,7 +41,6 @@ const lockMaintenanceConfig = { ...config, isLockFileMaintenance: true };
 
 describe('modules/manager/pip-compile/artifacts', () => {
   beforeEach(() => {
-    jest.resetAllMocks();
     env.getChildProcessEnv.mockReturnValue({
       ...envMock.basic,
       LANG: 'en_US.UTF-8',
diff --git a/lib/modules/manager/pip_requirements/artifacts.spec.ts b/lib/modules/manager/pip_requirements/artifacts.spec.ts
index 78ed52537d..314a591e70 100644
--- a/lib/modules/manager/pip_requirements/artifacts.spec.ts
+++ b/lib/modules/manager/pip_requirements/artifacts.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import { join } from 'upath';
 import { mockExecAll } from '../../../../test/exec-util';
 import { fs, mocked } from '../../../../test/util';
@@ -11,7 +12,7 @@ const datasource = mocked(_datasource);
 
 jest.mock('../../../util/exec/common');
 jest.mock('../../../util/fs');
-jest.mock('../../datasource');
+jest.mock('../../datasource', () => mockDeep());
 
 process.env.CONTAINERBASE = 'true';
 
@@ -41,8 +42,6 @@ botocore==1.27.46 \
 
 describe('modules/manager/pip_requirements/artifacts', () => {
   beforeEach(() => {
-    jest.resetAllMocks();
-    jest.resetModules();
     GlobalConfig.set(adminConfig);
   });
 
diff --git a/lib/modules/manager/pipenv/artifacts.spec.ts b/lib/modules/manager/pipenv/artifacts.spec.ts
index 9765961960..2ecfd2d2b4 100644
--- a/lib/modules/manager/pipenv/artifacts.spec.ts
+++ b/lib/modules/manager/pipenv/artifacts.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import { join } from 'upath';
 import { envMock, mockExecAll } from '../../../../test/exec-util';
 import {
@@ -22,9 +23,9 @@ const datasource = mocked(_datasource);
 jest.mock('../../../util/exec/env');
 jest.mock('../../../util/git');
 jest.mock('../../../util/fs');
-jest.mock('../../../util/host-rules');
+jest.mock('../../../util/host-rules', () => mockDeep());
 jest.mock('../../../util/http');
-jest.mock('../../datasource');
+jest.mock('../../datasource', () => mockDeep());
 
 process.env.CONTAINERBASE = 'true';
 
@@ -50,7 +51,6 @@ describe('modules/manager/pipenv/artifacts', () => {
   let pipFileLock: any;
 
   beforeEach(() => {
-    jest.resetAllMocks();
     env.getChildProcessEnv.mockReturnValue({
       ...envMock.basic,
       LANG: 'en_US.UTF-8',
diff --git a/lib/modules/manager/poetry/artifacts.spec.ts b/lib/modules/manager/poetry/artifacts.spec.ts
index 72d2f8023a..1bd44b1c4a 100644
--- a/lib/modules/manager/poetry/artifacts.spec.ts
+++ b/lib/modules/manager/poetry/artifacts.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import { join } from 'upath';
 import { envMock, mockExecAll } from '../../../../test/exec-util';
 import { Fixtures } from '../../../../test/fixtures';
@@ -16,8 +17,8 @@ const pyproject10toml = Fixtures.get('pyproject.10.toml');
 
 jest.mock('../../../util/exec/env');
 jest.mock('../../../util/fs');
-jest.mock('../../datasource');
-jest.mock('../../../util/host-rules');
+jest.mock('../../datasource', () => mockDeep());
+jest.mock('../../../util/host-rules', () => mockDeep());
 
 process.env.CONTAINERBASE = 'true';
 
@@ -54,7 +55,6 @@ describe('modules/manager/poetry/artifacts', () => {
 
   describe('updateArtifacts', () => {
     beforeEach(() => {
-      jest.resetAllMocks();
       env.getChildProcessEnv.mockReturnValue(envMock.basic);
       GlobalConfig.set(adminConfig);
       docker.resetPrefetchedImages();
diff --git a/lib/modules/manager/pre-commit/extract.spec.ts b/lib/modules/manager/pre-commit/extract.spec.ts
index 73d8d7d8d1..cefbcfc632 100644
--- a/lib/modules/manager/pre-commit/extract.spec.ts
+++ b/lib/modules/manager/pre-commit/extract.spec.ts
@@ -1,9 +1,10 @@
+import { mockDeep } from 'jest-mock-extended';
 import { Fixtures } from '../../../../test/fixtures';
 import { mocked } from '../../../../test/util';
 import * as _hostRules from '../../../util/host-rules';
 import { extractPackageFile } from '.';
 
-jest.mock('../../../util/host-rules');
+jest.mock('../../../util/host-rules', () => mockDeep());
 const hostRules = mocked(_hostRules);
 const filename = '.pre-commit.yaml';
 
@@ -22,10 +23,6 @@ const enterpriseGitPrecommitConfig = Fixtures.get(
 
 describe('modules/manager/pre-commit/extract', () => {
   describe('extractPackageFile()', () => {
-    beforeEach(() => {
-      jest.resetAllMocks();
-    });
-
     it('returns null for invalid yaml file content', () => {
       const result = extractPackageFile('nothing here: [', filename);
       expect(result).toBeNull();
diff --git a/lib/modules/manager/pub/artifacts.spec.ts b/lib/modules/manager/pub/artifacts.spec.ts
index e291049d1b..762158dade 100644
--- a/lib/modules/manager/pub/artifacts.spec.ts
+++ b/lib/modules/manager/pub/artifacts.spec.ts
@@ -1,4 +1,5 @@
 import { codeBlock } from 'common-tags';
+import { mockDeep } from 'jest-mock-extended';
 import { join } from 'upath';
 import { envMock, mockExecAll } from '../../../../test/exec-util';
 import { env, fs, mocked } from '../../../../test/util';
@@ -13,7 +14,7 @@ jest.mock('../../../util/exec/env');
 jest.mock('../../../util/fs');
 jest.mock('../../../util/git');
 jest.mock('../../../util/http');
-jest.mock('../../datasource');
+jest.mock('../../datasource', () => mockDeep());
 
 process.env.CONTAINERBASE = 'true';
 
@@ -45,8 +46,6 @@ const updateArtifact: UpdateArtifact = {
 
 describe('modules/manager/pub/artifacts', () => {
   beforeEach(() => {
-    jest.resetAllMocks();
-
     env.getChildProcessEnv.mockReturnValue(envMock.basic);
     GlobalConfig.set(adminConfig);
     docker.resetPrefetchedImages();
diff --git a/lib/modules/manager/terraform/lockfile/hash.spec.ts b/lib/modules/manager/terraform/lockfile/hash.spec.ts
index 6f123877f2..149d0e2291 100644
--- a/lib/modules/manager/terraform/lockfile/hash.spec.ts
+++ b/lib/modules/manager/terraform/lockfile/hash.spec.ts
@@ -4,14 +4,13 @@ import { Fixtures } from '../../../../../test/fixtures';
 import * as httpMock from '../../../../../test/http-mock';
 import { getFixturePath, logger } from '../../../../../test/util';
 import { GlobalConfig } from '../../../../config/global';
-import type { Logger } from '../../../../logger/types';
 import { TerraformProviderDatasource } from '../../../datasource/terraform-provider';
 import { TerraformProviderHash } from './hash';
 
 const releaseBackendUrl = TerraformProviderDatasource.defaultRegistryUrls[1];
 const releaseBackendAzurerm = Fixtures.get('releaseBackendAzurerm_2_56_0.json');
 
-const log = logger.logger as jest.Mocked<Logger>;
+const log = logger.logger;
 
 describe('modules/manager/terraform/lockfile/hash', () => {
   let cacheDir: DirectoryResult;
diff --git a/lib/modules/manager/terraform/lockfile/index.spec.ts b/lib/modules/manager/terraform/lockfile/index.spec.ts
index 75e4c93c48..a04fbd3602 100644
--- a/lib/modules/manager/terraform/lockfile/index.spec.ts
+++ b/lib/modules/manager/terraform/lockfile/index.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import { join } from 'upath';
 import { Fixtures } from '../../../../../test/fixtures';
 import { fs, mocked } from '../../../../../test/util';
@@ -10,7 +11,7 @@ import { TerraformProviderHash } from './hash';
 // auto-mock fs
 jest.mock('../../../../util/fs');
 jest.mock('./hash');
-jest.mock('../../../datasource');
+jest.mock('../../../datasource', () => mockDeep());
 
 const config = {
   constraints: {},
@@ -33,8 +34,6 @@ const mockGetPkgReleases = getPkgReleases as jest.MockedFunction<
 
 describe('modules/manager/terraform/lockfile/index', () => {
   beforeEach(() => {
-    jest.resetAllMocks();
-    jest.resetModules();
     GlobalConfig.set(adminConfig);
   });
 
diff --git a/lib/modules/platform/azure/azure-got-wrapper.spec.ts b/lib/modules/platform/azure/azure-got-wrapper.spec.ts
index 6b8498e378..57c21e0a0d 100644
--- a/lib/modules/platform/azure/azure-got-wrapper.spec.ts
+++ b/lib/modules/platform/azure/azure-got-wrapper.spec.ts
@@ -4,11 +4,11 @@ describe('modules/platform/azure/azure-got-wrapper', () => {
   let azure: typeof import('./azure-got-wrapper');
   let hostRules: typeof _hostRules;
 
-  beforeEach(() => {
+  beforeEach(async () => {
     // reset module
     jest.resetModules();
-    hostRules = require('../../../util/host-rules');
-    azure = require('./azure-got-wrapper');
+    hostRules = await import('../../../util/host-rules');
+    azure = await import('./azure-got-wrapper');
   });
 
   describe('gitApi', () => {
diff --git a/lib/modules/platform/azure/azure-helper.spec.ts b/lib/modules/platform/azure/azure-helper.spec.ts
index 2a94b6b652..d1cb1a939a 100644
--- a/lib/modules/platform/azure/azure-helper.spec.ts
+++ b/lib/modules/platform/azure/azure-helper.spec.ts
@@ -1,16 +1,17 @@
 import { Readable } from 'node:stream';
 import { GitPullRequestMergeStrategy } from 'azure-devops-node-api/interfaces/GitInterfaces.js';
 
+jest.mock('./azure-got-wrapper');
+
 describe('modules/platform/azure/azure-helper', () => {
   let azureHelper: typeof import('./azure-helper');
   let azureApi: jest.Mocked<typeof import('./azure-got-wrapper')>;
 
-  beforeEach(() => {
+  beforeEach(async () => {
     // reset module
     jest.resetModules();
-    jest.mock('./azure-got-wrapper');
-    azureHelper = require('./azure-helper');
-    azureApi = require('./azure-got-wrapper');
+    azureHelper = await import('./azure-helper');
+    azureApi = jest.requireMock('./azure-got-wrapper');
   });
 
   describe('getRef', () => {
diff --git a/lib/modules/platform/azure/index.spec.ts b/lib/modules/platform/azure/index.spec.ts
index 3c99d2dff0..bc8ea958da 100644
--- a/lib/modules/platform/azure/index.spec.ts
+++ b/lib/modules/platform/azure/index.spec.ts
@@ -6,7 +6,8 @@ import {
   GitStatusState,
   PullRequestStatus,
 } from 'azure-devops-node-api/interfaces/GitInterfaces.js';
-import { partial } from '../../../../test/util';
+import { mockDeep } from 'jest-mock-extended';
+import { mocked, partial } from '../../../../test/util';
 import {
   REPOSITORY_ARCHIVED,
   REPOSITORY_NOT_FOUND,
@@ -17,30 +18,32 @@ import type * as _hostRules from '../../../util/host-rules';
 import type { Platform, RepoParams } from '../types';
 import { AzurePrVote } from './types';
 
+jest.mock('./azure-got-wrapper');
+jest.mock('./azure-helper');
+jest.mock('../../../util/git');
+jest.mock('../../../util/host-rules', () => mockDeep());
+jest.mock('../../../util/sanitize', () =>
+  mockDeep({ sanitize: (s: string) => s })
+);
+jest.mock('timers/promises');
+
 describe('modules/platform/azure/index', () => {
   let hostRules: jest.Mocked<typeof _hostRules>;
   let azure: Platform;
   let azureApi: jest.Mocked<typeof import('./azure-got-wrapper')>;
   let azureHelper: jest.Mocked<typeof import('./azure-helper')>;
   let git: jest.Mocked<typeof _git>;
-  let logger: jest.Mocked<typeof _logger>;
+  let logger: jest.MockedObject<typeof _logger>;
 
   beforeEach(async () => {
     // reset module
     jest.resetModules();
-    jest.mock('./azure-got-wrapper');
-    jest.mock('./azure-helper');
-    jest.mock('../../../util/git');
-    jest.mock('../../../util/host-rules');
-    jest.mock('../../../logger');
-    jest.mock('timers/promises');
-    hostRules = require('../../../util/host-rules');
-    require('../../../util/sanitize').sanitize = jest.fn((input) => input);
+    hostRules = jest.requireMock('../../../util/host-rules');
     azure = await import('.');
-    azureApi = require('./azure-got-wrapper');
-    azureHelper = require('./azure-helper');
-    logger = (await import('../../../logger')).logger as never;
-    git = require('../../../util/git');
+    azureApi = jest.requireMock('./azure-got-wrapper');
+    azureHelper = jest.requireMock('./azure-helper');
+    logger = mocked(await import('../../../logger')).logger;
+    git = jest.requireMock('../../../util/git');
     git.branchExists.mockReturnValue(true);
     git.isBranchBehindBase.mockResolvedValue(false);
     hostRules.find.mockReturnValue({
diff --git a/lib/modules/platform/bitbucket-server/index.spec.ts b/lib/modules/platform/bitbucket-server/index.spec.ts
index f2b5f4357a..9084bb165c 100644
--- a/lib/modules/platform/bitbucket-server/index.spec.ts
+++ b/lib/modules/platform/bitbucket-server/index.spec.ts
@@ -1,4 +1,5 @@
 import is from '@sindresorhus/is';
+import { mockDeep } from 'jest-mock-extended';
 import * as httpMock from '../../../../test/http-mock';
 import {
   REPOSITORY_CHANGED,
@@ -8,6 +9,10 @@ import {
 import type * as _git from '../../../util/git';
 import type { Platform } from '../types';
 
+jest.mock('timers/promises');
+jest.mock('../../../util/git');
+jest.mock('../../../util/host-rules', () => mockDeep());
+
 function sshLink(projectKey: string, repositorySlug: string): string {
   return `ssh://git@stash.renovatebot.com:7999/${projectKey.toLowerCase()}/${repositorySlug}.git`;
 }
@@ -167,6 +172,8 @@ const scenarios = {
   'endpoint with path': new URL('https://stash.renovatebot.com/vcs'),
 };
 
+type HostRules = typeof import('../../../util/host-rules');
+
 describe('modules/platform/bitbucket-server/index', () => {
   Object.entries(scenarios).forEach(([scenarioName, url]) => {
     const urlHost = url.origin;
@@ -174,7 +181,8 @@ describe('modules/platform/bitbucket-server/index', () => {
 
     describe(scenarioName, () => {
       let bitbucket: Platform;
-      let hostRules: jest.Mocked<typeof import('../../../util/host-rules')>;
+
+      let hostRules: jest.Mocked<HostRules>;
       let git: jest.Mocked<typeof _git>;
       const username = 'abc';
       const password = '123';
@@ -201,12 +209,9 @@ describe('modules/platform/bitbucket-server/index', () => {
       beforeEach(async () => {
         // reset module
         jest.resetModules();
-        jest.mock('timers/promises');
-        jest.mock('../../../util/git');
-        jest.mock('../../../util/host-rules');
-        hostRules = require('../../../util/host-rules');
         bitbucket = await import('.');
-        git = require('../../../util/git');
+        hostRules = jest.requireMock('../../../util/host-rules');
+        git = jest.requireMock('../../../util/git');
         git.branchExists.mockReturnValue(true);
         git.isBranchBehindBase.mockResolvedValue(false);
         git.getBranchCommit.mockReturnValue(
diff --git a/lib/modules/platform/bitbucket/index.spec.ts b/lib/modules/platform/bitbucket/index.spec.ts
index 603bb2b5e9..5070c06724 100644
--- a/lib/modules/platform/bitbucket/index.spec.ts
+++ b/lib/modules/platform/bitbucket/index.spec.ts
@@ -4,6 +4,9 @@ import type * as _git from '../../../util/git';
 import { setBaseUrl } from '../../../util/http/bitbucket';
 import type { Platform, PlatformResult, RepoParams } from '../types';
 
+jest.mock('../../../util/git');
+jest.mock('../../../util/host-rules');
+
 const baseUrl = 'https://api.bitbucket.org';
 
 const pr = {
@@ -25,13 +28,10 @@ describe('modules/platform/bitbucket/index', () => {
   beforeEach(async () => {
     // reset module
     jest.resetModules();
-    jest.mock('../../../util/git');
-    jest.mock('../../../util/host-rules');
-    jest.mock('../../../logger');
-    hostRules = require('../../../util/host-rules');
+    hostRules = jest.requireMock('../../../util/host-rules');
     bitbucket = await import('.');
     logger = (await import('../../../logger')).logger as any;
-    git = require('../../../util/git');
+    git = jest.requireMock('../../../util/git');
     git.branchExists.mockReturnValue(true);
     git.isBranchBehindBase.mockResolvedValue(false);
     // clean up hostRules
diff --git a/lib/modules/platform/comment.spec.ts b/lib/modules/platform/comment.spec.ts
index 58fa3406ea..54a7116b3a 100644
--- a/lib/modules/platform/comment.spec.ts
+++ b/lib/modules/platform/comment.spec.ts
@@ -13,7 +13,7 @@ describe('modules/platform/comment', () => {
 
   beforeEach(() => {
     repoCache = {};
-    jest.resetAllMocks();
+
     cache.getCache.mockReturnValue(repoCache);
   });
 
diff --git a/lib/modules/platform/gitea/gitea-helper.spec.ts b/lib/modules/platform/gitea/gitea-helper.spec.ts
index 098699d88a..d1cd252983 100644
--- a/lib/modules/platform/gitea/gitea-helper.spec.ts
+++ b/lib/modules/platform/gitea/gitea-helper.spec.ts
@@ -184,7 +184,6 @@ describe('modules/platform/gitea/gitea-helper', () => {
   };
 
   beforeEach(() => {
-    jest.resetAllMocks();
     setBaseUrl(giteaApiHost);
   });
 
diff --git a/lib/modules/platform/gitea/index.spec.ts b/lib/modules/platform/gitea/index.spec.ts
index ce8604ed61..140925dec6 100644
--- a/lib/modules/platform/gitea/index.spec.ts
+++ b/lib/modules/platform/gitea/index.spec.ts
@@ -35,6 +35,9 @@ import type {
   User,
 } from './types';
 
+jest.mock('./gitea-helper');
+jest.mock('../../../util/git');
+
 /**
  * latest tested gitea version.
  */
@@ -45,7 +48,7 @@ describe('modules/platform/gitea/index', () => {
   let helper: jest.Mocked<typeof import('./gitea-helper')>;
   let logger: jest.Mocked<typeof _logger>;
   let gitvcs: jest.Mocked<typeof _git>;
-  let hostRules: jest.Mocked<typeof import('../../../util/host-rules')>;
+  let hostRules: typeof import('../../../util/host-rules');
 
   const mockCommitHash = '0d9c7726c3d628b7e28af234595cfd20febdbf8e';
 
@@ -199,17 +202,14 @@ describe('modules/platform/gitea/index', () => {
 
   beforeEach(async () => {
     jest.resetModules();
-    jest.mock('./gitea-helper');
-    jest.mock('../../../util/git');
-    jest.mock('../../../logger');
 
     gitea = await import('.');
-    helper = mocked(await import('./gitea-helper'));
-    logger = mocked((await import('../../../logger')).logger);
-    gitvcs = require('../../../util/git');
+    helper = jest.requireMock('./gitea-helper');
+    logger = mocked(await import('../../../logger')).logger;
+    gitvcs = jest.requireMock('../../../util/git');
     gitvcs.isBranchBehindBase.mockResolvedValue(false);
     gitvcs.getBranchCommit.mockReturnValue(mockCommitHash);
-    hostRules = mocked(await import('../../../util/host-rules'));
+    hostRules = await import('../../../util/host-rules');
     hostRules.clear();
 
     setBaseUrl('https://gitea.renovatebot.com/');
diff --git a/lib/modules/platform/github/index.spec.ts b/lib/modules/platform/github/index.spec.ts
index b08a7c13a3..0a5cdbc72d 100644
--- a/lib/modules/platform/github/index.spec.ts
+++ b/lib/modules/platform/github/index.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import { DateTime } from 'luxon';
 import * as httpMock from '../../../../test/http-mock';
 import { logger, mocked, partial } from '../../../../test/util';
@@ -24,7 +25,7 @@ const githubApiHost = 'https://api.github.com';
 
 jest.mock('timers/promises');
 
-jest.mock('../../../util/host-rules');
+jest.mock('../../../util/host-rules', () => mockDeep());
 jest.mock('../../../util/http/queue');
 const hostRules: jest.Mocked<typeof _hostRules> = mocked(_hostRules);
 
@@ -33,7 +34,6 @@ const git: jest.Mocked<typeof _git> = mocked(_git);
 
 describe('modules/platform/github/index', () => {
   beforeEach(() => {
-    jest.resetAllMocks();
     github.resetConfigs();
 
     setBaseUrl(githubApiHost);
diff --git a/lib/modules/platform/gitlab/index.spec.ts b/lib/modules/platform/gitlab/index.spec.ts
index 047f14dac5..f6f9e32203 100644
--- a/lib/modules/platform/gitlab/index.spec.ts
+++ b/lib/modules/platform/gitlab/index.spec.ts
@@ -1,7 +1,9 @@
 // TODO fix mocks
 import type * as _timers from 'timers/promises';
+import { mockDeep } from 'jest-mock-extended';
 import type { Platform, RepoParams } from '..';
 import * as httpMock from '../../../../test/http-mock';
+import { mocked } from '../../../../test/util';
 import {
   CONFIG_GIT_URL_UNAVAILABLE,
   REPOSITORY_ARCHIVED,
@@ -16,6 +18,10 @@ import type * as _git from '../../../util/git';
 import type * as _hostRules from '../../../util/host-rules';
 import { toBase64 } from '../../../util/string';
 
+jest.mock('../../../util/host-rules', () => mockDeep());
+jest.mock('../../../util/git');
+jest.mock('timers/promises');
+
 const gitlabApiHost = 'https://gitlab.com';
 
 describe('modules/platform/gitlab/index', () => {
@@ -28,16 +34,12 @@ describe('modules/platform/gitlab/index', () => {
   beforeEach(async () => {
     // reset module
     jest.resetModules();
-    jest.resetAllMocks();
+
     gitlab = await import('.');
-    jest.mock('../../../logger');
-    logger = (await import('../../../logger')).logger as never;
-    jest.mock('../../../util/host-rules');
-    jest.mock('timers/promises');
-    timers = require('timers/promises');
-    hostRules = require('../../../util/host-rules');
-    jest.mock('../../../util/git');
-    git = require('../../../util/git');
+    logger = mocked(await import('../../../logger')).logger;
+    timers = jest.requireMock('timers/promises');
+    hostRules = jest.requireMock('../../../util/host-rules');
+    git = jest.requireMock('../../../util/git');
     git.branchExists.mockReturnValue(true);
     git.isBranchBehindBase.mockResolvedValue(true);
     git.getBranchCommit.mockReturnValue(
@@ -2295,8 +2297,6 @@ describe('modules/platform/gitlab/index', () => {
   });
 
   describe('updatePr(prNo, title, body)', () => {
-    jest.resetAllMocks();
-
     it('updates the PR', async () => {
       await initPlatform('13.3.6-ee');
       httpMock
@@ -2452,8 +2452,6 @@ describe('modules/platform/gitlab/index', () => {
   });
 
   describe('mergePr(pr)', () => {
-    jest.resetAllMocks();
-
     it('merges the PR', async () => {
       httpMock
         .scope(gitlabApiHost)
@@ -2499,8 +2497,8 @@ These updates have all been created already. Click a checkbox below to force a r
     });
 
     it('returns updated pr body', async () => {
-      jest.mock('../utils/pr-body');
-      const { smartTruncate } = require('../utils/pr-body');
+      jest.doMock('../utils/pr-body');
+      const { smartTruncate } = await import('../utils/pr-body');
 
       await initFakePlatform('13.4.0');
       expect(gitlab.massageMarkdown(prBody)).toMatchSnapshot();
@@ -2508,8 +2506,8 @@ These updates have all been created already. Click a checkbox below to force a r
     });
 
     it('truncates description if too low API version', async () => {
-      jest.mock('../utils/pr-body');
-      const { smartTruncate } = require('../utils/pr-body');
+      jest.doMock('../utils/pr-body');
+      const { smartTruncate } = await import('../utils/pr-body');
 
       await initFakePlatform('13.3.0');
       gitlab.massageMarkdown(prBody);
@@ -2518,8 +2516,8 @@ These updates have all been created already. Click a checkbox below to force a r
     });
 
     it('truncates description for API version gt 13.4', async () => {
-      jest.mock('../utils/pr-body');
-      const { smartTruncate } = require('../utils/pr-body');
+      jest.doMock('../utils/pr-body');
+      const { smartTruncate } = await import('../utils/pr-body');
 
       await initFakePlatform('13.4.1');
       gitlab.massageMarkdown(prBody);
diff --git a/lib/modules/platform/local/scm.spec.ts b/lib/modules/platform/local/scm.spec.ts
index 92efed3cf5..2b5b0c12ca 100644
--- a/lib/modules/platform/local/scm.spec.ts
+++ b/lib/modules/platform/local/scm.spec.ts
@@ -2,6 +2,9 @@ import { execSync as _execSync } from 'node:child_process';
 import { mockedFunction } from '../../../../test/util';
 import { LocalFs } from './scm';
 
+jest.mock('glob', () => ({
+  glob: jest.fn().mockImplementation(() => Promise.resolve(['file1', 'file2'])),
+}));
 jest.mock('node:child_process');
 const execSync = mockedFunction(_execSync);
 
@@ -56,11 +59,6 @@ describe('modules/platform/local/scm', () => {
       execSync.mockImplementationOnce(() => {
         throw new Error();
       });
-      jest.mock('glob', () => ({
-        glob: jest
-          .fn()
-          .mockImplementation(() => Promise.resolve(['file1', 'file2'])),
-      }));
 
       expect(await localFs.getFileList()).toHaveLength(2);
     });
diff --git a/lib/modules/versioning/index.spec.ts b/lib/modules/versioning/index.spec.ts
index 017d198e1b..a31f24ce94 100644
--- a/lib/modules/versioning/index.spec.ts
+++ b/lib/modules/versioning/index.spec.ts
@@ -106,7 +106,7 @@ describe('modules/versioning/index', () => {
     }
 
     for (const supportedScheme of supportedSchemes ?? []) {
-      it(supportedScheme, () => {
+      it(supportedScheme, async () => {
         const schemeKeys = getAllPropertyNames(
           allVersioning.get(supportedScheme)
         )
@@ -117,7 +117,7 @@ describe('modules/versioning/index', () => {
 
         expect(schemeKeys).toEqual(npmApi);
 
-        const apiOrCtor = require('./' + supportedScheme).api;
+        const apiOrCtor = (await import(`./${supportedScheme}`)).api;
         if (isVersioningApiConstructor(apiOrCtor)) {
           return;
         }
diff --git a/lib/modules/versioning/ubuntu/index.spec.ts b/lib/modules/versioning/ubuntu/index.spec.ts
index 116828621d..e2c56b9727 100644
--- a/lib/modules/versioning/ubuntu/index.spec.ts
+++ b/lib/modules/versioning/ubuntu/index.spec.ts
@@ -4,10 +4,6 @@ import { api as ubuntu } from '.';
 describe('modules/versioning/ubuntu/index', () => {
   const dt = DateTime.fromISO('2022-04-20');
 
-  afterEach(() => {
-    jest.resetAllMocks();
-  });
-
   it.each`
     version        | expected
     ${undefined}   | ${false}
diff --git a/lib/modules/versioning/versioning-metadata.spec.ts b/lib/modules/versioning/versioning-metadata.spec.ts
index ae5c1722df..28cfda606e 100644
--- a/lib/modules/versioning/versioning-metadata.spec.ts
+++ b/lib/modules/versioning/versioning-metadata.spec.ts
@@ -28,7 +28,7 @@ describe('modules/versioning/versioning-metadata', () => {
     );
 
     for (const versioning of allVersioning) {
-      const versioningObj = require(`./${versioning}`);
+      const versioningObj = await import(`./${versioning}`);
       expect(versioningObj.id).toEqual(versioning);
       expect(versioningObj.displayName).toBeDefined();
       expect(versioningObj.urls).toBeDefined();
diff --git a/lib/renovate.spec.ts b/lib/renovate.spec.ts
index 6df1d8b232..58efd7dcff 100644
--- a/lib/renovate.spec.ts
+++ b/lib/renovate.spec.ts
@@ -3,8 +3,8 @@ import * as renovateWorker from './workers/global';
 Object.defineProperty(renovateWorker, 'start', { value: jest.fn() });
 
 describe('renovate', () => {
-  it('starts', () => {
-    require('./renovate');
+  it('starts', async () => {
+    await import('./renovate');
     expect(renovateWorker.start).toHaveBeenCalledTimes(1);
   });
 });
diff --git a/lib/util/cache/package/decorator.spec.ts b/lib/util/cache/package/decorator.spec.ts
index e3d5de83da..eb5d333121 100644
--- a/lib/util/cache/package/decorator.spec.ts
+++ b/lib/util/cache/package/decorator.spec.ts
@@ -1,20 +1,21 @@
-import os from 'node:os';
 import { GlobalConfig } from '../../../config/global';
 import * as memCache from '../memory';
 import { cache } from './decorator';
+import * as file from './file';
 import * as packageCache from '.';
 
 jest.mock('./file');
 
 describe('util/cache/package/decorator', () => {
-  const setCache = jest.spyOn(packageCache, 'set');
-
-  let count = 1;
+  const setCache = file.set;
   const getValue = jest.fn();
+  let count = 1;
 
   beforeEach(async () => {
+    jest.useRealTimers();
+    GlobalConfig.reset();
     memCache.init();
-    await packageCache.init({ cacheDir: os.tmpdir() });
+    await packageCache.init({ cacheDir: 'some-dir' });
     count = 1;
     getValue.mockImplementation(() => {
       const res = String(100 * count + 10 * count + count);
@@ -170,15 +171,10 @@ describe('util/cache/package/decorator', () => {
     }
 
     beforeEach(() => {
-      jest.useFakeTimers({ advanceTimers: false });
+      jest.useFakeTimers();
       GlobalConfig.set({ cacheHardTtlMinutes: 2 });
     });
 
-    afterEach(() => {
-      jest.useRealTimers();
-      GlobalConfig.reset();
-    });
-
     it('updates cached result', async () => {
       const obj = new Class();
 
diff --git a/lib/util/cache/repository/impl/local.spec.ts b/lib/util/cache/repository/impl/local.spec.ts
index e3f6e1f78b..e02178f285 100644
--- a/lib/util/cache/repository/impl/local.spec.ts
+++ b/lib/util/cache/repository/impl/local.spec.ts
@@ -34,7 +34,6 @@ async function createCacheRecord(
 
 describe('util/cache/repository/impl/local', () => {
   beforeEach(() => {
-    jest.resetAllMocks();
     GlobalConfig.set({ cacheDir: '/tmp/cache', platform: 'github' });
     fs.cachePathExists.mockResolvedValue(true);
   });
diff --git a/lib/util/cache/repository/index.spec.ts b/lib/util/cache/repository/index.spec.ts
index 3bfe5a9093..b8158d58d9 100644
--- a/lib/util/cache/repository/index.spec.ts
+++ b/lib/util/cache/repository/index.spec.ts
@@ -13,7 +13,6 @@ const fs = mocked(_fs);
 describe('util/cache/repository/index', () => {
   beforeEach(() => {
     resetCache();
-    jest.resetAllMocks();
     GlobalConfig.set({ cacheDir: '/tmp/cache', platform: 'github' });
   });
 
diff --git a/lib/util/check-token.spec.ts b/lib/util/check-token.spec.ts
index 2251342441..67b95950c2 100644
--- a/lib/util/check-token.spec.ts
+++ b/lib/util/check-token.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import { hostRules, logger } from '../../test/util';
 import { GlobalConfig } from '../config/global';
 import { GithubReleasesDatasource } from '../modules/datasource/github-releases';
@@ -13,12 +14,11 @@ import {
   takePersonalAccessTokenIfPossible,
 } from './check-token';
 
-jest.mock('./host-rules');
+jest.mock('./host-rules', () => mockDeep());
 
 describe('util/check-token', () => {
   describe('checkGithubToken', () => {
     beforeEach(() => {
-      jest.resetAllMocks();
       memCache.reset();
       GlobalConfig.set({ githubTokenWarn: true });
     });
diff --git a/lib/util/exec/docker/index.spec.ts b/lib/util/exec/docker/index.spec.ts
index 376a8a523b..ab3eb066a1 100644
--- a/lib/util/exec/docker/index.spec.ts
+++ b/lib/util/exec/docker/index.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import { mockExecAll, mockExecSequence } from '../../../../test/exec-util';
 import { partial } from '../../../../test/util';
 import { GlobalConfig } from '../../../config/global';
@@ -15,13 +16,9 @@ import {
   sideCarImage,
 } from '.';
 
-jest.mock('../../../modules/datasource');
+jest.mock('../../../modules/datasource', () => mockDeep());
 
 describe('util/exec/docker/index', () => {
-  beforeEach(() => {
-    jest.resetAllMocks();
-  });
-
   describe('prefetchDockerImage', () => {
     beforeEach(() => {
       resetPrefetchedImages();
diff --git a/lib/util/exec/index.spec.ts b/lib/util/exec/index.spec.ts
index f545e08072..8aa42878ea 100644
--- a/lib/util/exec/index.spec.ts
+++ b/lib/util/exec/index.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import { exec as cpExec, envMock } from '../../../test/exec-util';
 import { mockedFunction } from '../../../test/util';
 import { GlobalConfig } from '../../config/global';
@@ -11,11 +12,10 @@ import { exec } from '.';
 const getHermitEnvsMock = mockedFunction(getHermitEnvs);
 
 jest.mock('./hermit', () => ({
-  // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
-  ...(jest.requireActual('./hermit') as any),
+  ...jest.requireActual<typeof import('./hermit')>('./hermit'),
   getHermitEnvs: jest.fn(),
 }));
-jest.mock('../../modules/datasource');
+jest.mock('../../modules/datasource', () => mockDeep());
 
 interface TestInput {
   processEnv: Record<string, string>;
@@ -46,7 +46,6 @@ describe('util/exec/index', () => {
 
   beforeEach(() => {
     dockerModule.resetPrefetchedImages();
-    jest.resetAllMocks();
     jest.restoreAllMocks();
     jest.resetModules();
     processEnvOrig = process.env;
diff --git a/lib/util/git/index.spec.ts b/lib/util/git/index.spec.ts
index 8d8c38225c..3902d862a4 100644
--- a/lib/util/git/index.spec.ts
+++ b/lib/util/git/index.spec.ts
@@ -892,10 +892,6 @@ describe('util/git/index', () => {
     });
 
     describe('cachedConflictResult', () => {
-      beforeEach(() => {
-        jest.resetAllMocks();
-      });
-
       it('returns cached values', async () => {
         conflictsCache.getCachedConflictResult.mockReturnValue(true);
 
diff --git a/lib/util/git/private-key.spec.ts b/lib/util/git/private-key.spec.ts
index 9ecbbe74f0..667b8c5853 100644
--- a/lib/util/git/private-key.spec.ts
+++ b/lib/util/git/private-key.spec.ts
@@ -1,10 +1,15 @@
-import { Fixtures } from '../../../test/fixtures';
 import { mocked } from '../../../test/util';
 import * as exec_ from '../exec';
 import { configSigningKey, writePrivateKey } from './private-key';
 import { setPrivateKey } from '.';
 
-jest.mock('fs-extra', () => Fixtures.fsExtra());
+jest.mock('fs-extra', () =>
+  jest
+    .requireActual<typeof import('../../../test/fixtures')>(
+      '../../../test/fixtures'
+    )
+    .fsExtra()
+);
 jest.mock('../exec');
 
 const exec = mocked(exec_);
diff --git a/lib/util/git/semantic.spec.ts b/lib/util/git/semantic.spec.ts
index d15876b9be..cea1cd399b 100644
--- a/lib/util/git/semantic.spec.ts
+++ b/lib/util/git/semantic.spec.ts
@@ -7,7 +7,6 @@ jest.mock('.');
 let config: RenovateConfig;
 
 beforeEach(() => {
-  jest.resetAllMocks();
   config = partial<RenovateConfig>();
 });
 
diff --git a/lib/util/git/url.spec.ts b/lib/util/git/url.spec.ts
index ca32e45f8a..194e653775 100644
--- a/lib/util/git/url.spec.ts
+++ b/lib/util/git/url.spec.ts
@@ -1,7 +1,8 @@
+import { mockDeep } from 'jest-mock-extended';
 import { hostRules } from '../../../test/util';
 import { getHttpUrl, getRemoteUrlWithToken, parseGitUrl } from './url';
 
-jest.mock('../host-rules');
+jest.mock('../host-rules', () => mockDeep());
 
 describe('util/git/url', () => {
   describe('parseGitUrl', () => {
diff --git a/lib/util/github/graphql/cache-strategies/memory-cache-strategy.spec.ts b/lib/util/github/graphql/cache-strategies/memory-cache-strategy.spec.ts
index 88849193a1..13bd58bceb 100644
--- a/lib/util/github/graphql/cache-strategies/memory-cache-strategy.spec.ts
+++ b/lib/util/github/graphql/cache-strategies/memory-cache-strategy.spec.ts
@@ -33,7 +33,6 @@ type CacheRecord = GithubGraphqlCacheRecord<GithubDatasourceItem>;
 
 describe('util/github/graphql/cache-strategies/memory-cache-strategy', () => {
   beforeEach(() => {
-    jest.resetAllMocks();
     memCache.init();
   });
 
diff --git a/lib/util/github/graphql/datasource-fetcher.spec.ts b/lib/util/github/graphql/datasource-fetcher.spec.ts
index bed035a564..f2c76fdb8f 100644
--- a/lib/util/github/graphql/datasource-fetcher.spec.ts
+++ b/lib/util/github/graphql/datasource-fetcher.spec.ts
@@ -108,7 +108,6 @@ describe('util/github/graphql/datasource-fetcher', () => {
     const t3 = '01-01-2023';
 
     beforeEach(() => {
-      jest.resetAllMocks();
       http = new GithubHttp();
     });
 
diff --git a/lib/util/http/bitbucket-server.spec.ts b/lib/util/http/bitbucket-server.spec.ts
index 56d331f72c..238e08a4e9 100644
--- a/lib/util/http/bitbucket-server.spec.ts
+++ b/lib/util/http/bitbucket-server.spec.ts
@@ -10,9 +10,6 @@ describe('util/http/bitbucket-server', () => {
   beforeEach(() => {
     api = new BitbucketServerHttp();
 
-    // reset module
-    jest.resetAllMocks();
-
     // clean up hostRules
     hostRules.clear();
     hostRules.add({
diff --git a/lib/util/http/bitbucket.spec.ts b/lib/util/http/bitbucket.spec.ts
index 16bf1956de..52cc342b7d 100644
--- a/lib/util/http/bitbucket.spec.ts
+++ b/lib/util/http/bitbucket.spec.ts
@@ -11,9 +11,6 @@ describe('util/http/bitbucket', () => {
   beforeEach(() => {
     api = new BitbucketHttp();
 
-    // reset module
-    jest.resetAllMocks();
-
     // clean up hostRules
     hostRules.clear();
     hostRules.add({
diff --git a/lib/util/http/gitea.spec.ts b/lib/util/http/gitea.spec.ts
index cc7426638b..3e9b7bd0e7 100644
--- a/lib/util/http/gitea.spec.ts
+++ b/lib/util/http/gitea.spec.ts
@@ -9,8 +9,6 @@ describe('util/http/gitea', () => {
   beforeEach(() => {
     giteaHttp = new GiteaHttp();
 
-    jest.resetAllMocks();
-
     setBaseUrl(baseUrl);
   });
 
diff --git a/lib/util/http/github.spec.ts b/lib/util/http/github.spec.ts
index fe85535129..5d66f42fba 100644
--- a/lib/util/http/github.spec.ts
+++ b/lib/util/http/github.spec.ts
@@ -55,7 +55,6 @@ describe('util/http/github', () => {
     delete process.env.RENOVATE_X_REBASE_PAGINATION_LINKS;
     githubApi = new GithubHttp();
     setBaseUrl(githubApiHost);
-    jest.resetAllMocks();
     repoCache = {};
     repositoryCache.getCache.mockReturnValue(repoCache);
   });
diff --git a/lib/util/http/gitlab.spec.ts b/lib/util/http/gitlab.spec.ts
index 38dbb79e45..7a63dd6a11 100644
--- a/lib/util/http/gitlab.spec.ts
+++ b/lib/util/http/gitlab.spec.ts
@@ -27,8 +27,6 @@ describe('util/http/gitlab', () => {
   });
 
   afterEach(() => {
-    jest.resetAllMocks();
-
     hostRules.clear();
   });
 
diff --git a/lib/util/http/host-rules.spec.ts b/lib/util/http/host-rules.spec.ts
index 6ad1f655b5..6b8667d70c 100644
--- a/lib/util/http/host-rules.spec.ts
+++ b/lib/util/http/host-rules.spec.ts
@@ -14,9 +14,6 @@ describe('util/http/host-rules', () => {
   };
 
   beforeEach(() => {
-    // reset module
-    jest.resetAllMocks();
-
     delete process.env.HTTP_PROXY;
 
     // clean up hostRules
diff --git a/lib/util/http/index.spec.ts b/lib/util/http/index.spec.ts
index 49f9f1aff0..304a368c6f 100644
--- a/lib/util/http/index.spec.ts
+++ b/lib/util/http/index.spec.ts
@@ -320,7 +320,6 @@ describe('util/http/index', () => {
       .transform(({ x, y }) => `${x} + ${y} = ${x + y}`);
 
     beforeEach(() => {
-      jest.resetAllMocks();
       memCache.init();
     });
 
diff --git a/lib/util/json-writer/editor-config.spec.ts b/lib/util/json-writer/editor-config.spec.ts
index 855844ff47..0139c90766 100644
--- a/lib/util/json-writer/editor-config.spec.ts
+++ b/lib/util/json-writer/editor-config.spec.ts
@@ -5,16 +5,18 @@ import { GlobalConfig } from '../../config/global';
 import { EditorConfig } from './editor-config';
 
 // use real fs to read wasm files for `@one-ini/wasm`
-jest.mock('fs', () => ({
-  ...memfs,
-  readFileSync: (file: string, ...args: any[]) => {
-    if (file.endsWith('.wasm')) {
-      const realFs = jest.requireActual<typeof import('fs')>('fs');
-      return realFs.readFileSync(file, ...args);
-    }
-    return memfs.readFileSync(file, ...args);
-  },
-}));
+jest.mock('fs', () => {
+  const realFs = jest.requireActual<typeof import('fs')>('fs');
+  return {
+    ...memfs,
+    readFileSync: (file: string, ...args: any[]) => {
+      if (file.endsWith('.wasm')) {
+        return realFs.readFileSync(file, ...args);
+      }
+      return memfs.readFileSync(file, ...args);
+    },
+  };
+});
 
 const defaultConfigFile = configFileNames[0];
 
@@ -26,6 +28,7 @@ describe('util/json-writer/editor-config', () => {
   });
 
   beforeEach(() => {
+    jest.restoreAllMocks();
     Fixtures.reset();
   });
 
diff --git a/lib/util/merge-confidence/index.spec.ts b/lib/util/merge-confidence/index.spec.ts
index d256fe3314..2fc566b37c 100644
--- a/lib/util/merge-confidence/index.spec.ts
+++ b/lib/util/merge-confidence/index.spec.ts
@@ -56,7 +56,6 @@ describe('util/merge-confidence/index', () => {
     };
 
     beforeEach(() => {
-      jest.resetAllMocks();
       process.env.RENOVATE_X_MERGE_CONFIDENCE_API_BASE_URL = apiBaseUrl;
       hostRules.add(hostRule);
       initConfig();
diff --git a/lib/util/regex.spec.ts b/lib/util/regex.spec.ts
index 3283c40ec1..6125984dc8 100644
--- a/lib/util/regex.spec.ts
+++ b/lib/util/regex.spec.ts
@@ -29,12 +29,12 @@ describe('util/regex', () => {
     expect(regEx(/bar/g)).not.toBe(/bar/g);
   });
 
-  it('Falls back to RegExp', () => {
+  it('Falls back to RegExp', async () => {
     jest.doMock('re2', () => {
       throw new Error();
     });
 
-    const regex = require('./regex');
+    const regex = await import('./regex');
     expect(regex.regEx('foo')).toBeInstanceOf(RegExp);
   });
 
diff --git a/lib/workers/global/autodiscover.spec.ts b/lib/workers/global/autodiscover.spec.ts
index 6566d0ac99..8889ec09af 100644
--- a/lib/workers/global/autodiscover.spec.ts
+++ b/lib/workers/global/autodiscover.spec.ts
@@ -16,7 +16,6 @@ describe('workers/global/autodiscover', () => {
   let config: RenovateConfig;
 
   beforeEach(async () => {
-    jest.resetAllMocks();
     config = {};
     await platform.initPlatform({
       platform: 'github',
diff --git a/lib/workers/global/config/parse/file.spec.ts b/lib/workers/global/config/parse/file.spec.ts
index 0a786e8f80..05fcc01fb8 100644
--- a/lib/workers/global/config/parse/file.spec.ts
+++ b/lib/workers/global/config/parse/file.spec.ts
@@ -134,7 +134,9 @@ describe('workers/global/config/parse/file', () => {
       fsRemoveSpy.mockImplementationOnce(() => {
         // no-op
       });
-      fsPathExistsSpy.mockResolvedValueOnce(true as never);
+      fsPathExistsSpy
+        .mockResolvedValueOnce(true as never)
+        .mockResolvedValueOnce(true as never);
       const configFile = upath.resolve(tmp.path, './config.json');
       fs.writeFileSync(configFile, `{"token": "abc"}`, { encoding: 'utf8' });
 
diff --git a/lib/workers/global/config/parse/index.spec.ts b/lib/workers/global/config/parse/index.spec.ts
index d7cf9ebce0..6301ecc3f2 100644
--- a/lib/workers/global/config/parse/index.spec.ts
+++ b/lib/workers/global/config/parse/index.spec.ts
@@ -7,11 +7,7 @@ import * as _hostRulesFromEnv from './host-rules-from-env';
 jest.mock('../../../../modules/datasource/npm');
 jest.mock('../../../../util/fs');
 jest.mock('./host-rules-from-env');
-try {
-  jest.mock('../../config.js');
-} catch (err) {
-  // file does not exist
-}
+jest.mock('../../config.js', () => ({}), { virtual: true });
 
 const { hostRulesFromEnv } = mocked(_hostRulesFromEnv);
 
diff --git a/lib/workers/global/index.spec.ts b/lib/workers/global/index.spec.ts
index 0bc6aec1ad..f950d5b4b0 100644
--- a/lib/workers/global/index.spec.ts
+++ b/lib/workers/global/index.spec.ts
@@ -1,4 +1,3 @@
-import { expect } from '@jest/globals';
 import { ERROR, WARN } from 'bunyan';
 import fs from 'fs-extra';
 import { logger, mocked } from '../../../test/util';
diff --git a/lib/workers/repository/config-migration/branch/commit-message.spec.ts b/lib/workers/repository/config-migration/branch/commit-message.spec.ts
index 48c7692e86..a2ab74b131 100644
--- a/lib/workers/repository/config-migration/branch/commit-message.spec.ts
+++ b/lib/workers/repository/config-migration/branch/commit-message.spec.ts
@@ -5,10 +5,6 @@ describe('workers/repository/config-migration/branch/commit-message', () => {
   const config = getConfig();
   const fileName = 'renovate.json';
 
-  afterAll(() => {
-    jest.resetAllMocks();
-  });
-
   it('creates semantic commit message', () => {
     config.semanticCommits = 'enabled';
     const commitMessageFactory = new ConfigMigrationCommitMessageFactory(
diff --git a/lib/workers/repository/config-migration/branch/index.spec.ts b/lib/workers/repository/config-migration/branch/index.spec.ts
index 9b1dab3e4e..3d4754978b 100644
--- a/lib/workers/repository/config-migration/branch/index.spec.ts
+++ b/lib/workers/repository/config-migration/branch/index.spec.ts
@@ -33,7 +33,6 @@ describe('workers/repository/config-migration/branch/index', () => {
       GlobalConfig.set({
         dryRun: null,
       });
-      jest.resetAllMocks();
       config = getConfig();
       config.branchPrefix = 'some/';
     });
diff --git a/lib/workers/repository/config-migration/branch/migrated-data.spec.ts b/lib/workers/repository/config-migration/branch/migrated-data.spec.ts
index db3b27b346..8e892b8409 100644
--- a/lib/workers/repository/config-migration/branch/migrated-data.spec.ts
+++ b/lib/workers/repository/config-migration/branch/migrated-data.spec.ts
@@ -26,7 +26,6 @@ const formattedMigratedData = Fixtures.getJson(
 describe('workers/repository/config-migration/branch/migrated-data', () => {
   describe('MigratedDataFactory.getAsync', () => {
     beforeEach(() => {
-      jest.resetAllMocks();
       mockedFunction(detectIndent).mockReturnValue({
         type: 'space',
         amount: 2,
diff --git a/lib/workers/repository/config-migration/index.spec.ts b/lib/workers/repository/config-migration/index.spec.ts
index eaed898146..9f10718939 100644
--- a/lib/workers/repository/config-migration/index.spec.ts
+++ b/lib/workers/repository/config-migration/index.spec.ts
@@ -21,7 +21,6 @@ const config = {
 
 describe('workers/repository/config-migration/index', () => {
   beforeEach(() => {
-    jest.resetAllMocks();
     mockedFunction(MigratedDataFactory.getAsync).mockResolvedValue({
       filename,
       content,
diff --git a/lib/workers/repository/config-migration/pr/index.spec.ts b/lib/workers/repository/config-migration/pr/index.spec.ts
index 25f4ab65f1..d577ac254f 100644
--- a/lib/workers/repository/config-migration/pr/index.spec.ts
+++ b/lib/workers/repository/config-migration/pr/index.spec.ts
@@ -37,7 +37,7 @@ describe('workers/repository/config-migration/pr/index', () => {
     GlobalConfig.set({
       dryRun: null,
     });
-    jest.resetAllMocks();
+
     config = {
       ...getConfig(),
       configMigration: true,
@@ -251,7 +251,6 @@ describe('workers/repository/config-migration/pr/index', () => {
     const err = partial<RequestError>({ response });
 
     beforeEach(() => {
-      jest.resetAllMocks();
       GlobalConfig.reset();
       scm.deleteBranch.mockResolvedValue();
     });
diff --git a/lib/workers/repository/configured.spec.ts b/lib/workers/repository/configured.spec.ts
index c219be9444..c7c4113d32 100644
--- a/lib/workers/repository/configured.spec.ts
+++ b/lib/workers/repository/configured.spec.ts
@@ -4,7 +4,6 @@ import { checkIfConfigured } from './configured';
 let config: RenovateConfig;
 
 beforeEach(() => {
-  jest.resetAllMocks();
   config = partial<RenovateConfig>({
     enabled: true,
     forkProcessing: 'auto',
diff --git a/lib/workers/repository/dependency-dashboard.spec.ts b/lib/workers/repository/dependency-dashboard.spec.ts
index 0f22e3e558..318631a68b 100644
--- a/lib/workers/repository/dependency-dashboard.spec.ts
+++ b/lib/workers/repository/dependency-dashboard.spec.ts
@@ -1021,10 +1021,6 @@ describe('workers/repository/dependency-dashboard', () => {
           PackageFiles.clear();
         });
 
-        afterAll(() => {
-          jest.resetAllMocks();
-        });
-
         it('does not truncates as there is enough space to fit', () => {
           PackageFiles.add('main', packageFiles);
           const nonTruncated = PackageFiles.getDashboardMarkdown(Infinity);
diff --git a/lib/workers/repository/error-config.spec.ts b/lib/workers/repository/error-config.spec.ts
index 2eb296e73a..7731fb58c2 100644
--- a/lib/workers/repository/error-config.spec.ts
+++ b/lib/workers/repository/error-config.spec.ts
@@ -14,7 +14,6 @@ jest.mock('../../modules/platform');
 let config: RenovateConfig;
 
 beforeEach(() => {
-  jest.resetAllMocks();
   // default values
   config = partial<RenovateConfig>({
     onboardingBranch: 'configure/renovate',
diff --git a/lib/workers/repository/error.spec.ts b/lib/workers/repository/error.spec.ts
index 07cd0838ed..f643a7f540 100644
--- a/lib/workers/repository/error.spec.ts
+++ b/lib/workers/repository/error.spec.ts
@@ -36,7 +36,6 @@ jest.mock('./error-config');
 let config: RenovateConfig;
 
 beforeEach(() => {
-  jest.resetAllMocks();
   config = partial<RenovateConfig>({ branchList: [] });
 });
 
diff --git a/lib/workers/repository/errors-warnings.spec.ts b/lib/workers/repository/errors-warnings.spec.ts
index f7f1b91c7a..2123c92000 100644
--- a/lib/workers/repository/errors-warnings.spec.ts
+++ b/lib/workers/repository/errors-warnings.spec.ts
@@ -13,7 +13,6 @@ describe('workers/repository/errors-warnings', () => {
     let config: RenovateConfig;
 
     beforeEach(() => {
-      jest.resetAllMocks();
       config = partial<RenovateConfig>();
     });
 
@@ -46,10 +45,6 @@ describe('workers/repository/errors-warnings', () => {
   });
 
   describe('getDepWarningsPR()', () => {
-    beforeEach(() => {
-      jest.resetAllMocks();
-    });
-
     it('returns 2 pr warnings text dependencyDashboard true', () => {
       const config: RenovateConfig = {};
       const dependencyDashboard = true;
@@ -164,10 +159,6 @@ describe('workers/repository/errors-warnings', () => {
   });
 
   describe('getDepWarningsDashboard()', () => {
-    beforeEach(() => {
-      jest.resetAllMocks();
-    });
-
     it('returns dependency dashboard warning text', () => {
       const config: RenovateConfig = {};
       const packageFiles: Record<string, PackageFile[]> = {
@@ -239,7 +230,6 @@ describe('workers/repository/errors-warnings', () => {
     let config: RenovateConfig;
 
     beforeEach(() => {
-      jest.resetAllMocks();
       config = partial<RenovateConfig>();
     });
 
diff --git a/lib/workers/repository/extract/index.spec.ts b/lib/workers/repository/extract/index.spec.ts
index 5c21ec155a..7d257cbbc3 100644
--- a/lib/workers/repository/extract/index.spec.ts
+++ b/lib/workers/repository/extract/index.spec.ts
@@ -17,7 +17,6 @@ describe('workers/repository/extract/index', () => {
     const fileList = ['README', 'package.json', 'tasks/ansible.yaml'];
 
     beforeEach(() => {
-      jest.resetAllMocks();
       scm.getFileList.mockResolvedValue(fileList);
       config = getConfig();
     });
diff --git a/lib/workers/repository/extract/manager-files.spec.ts b/lib/workers/repository/extract/manager-files.spec.ts
index d081eab4b9..8f2fa4ff5d 100644
--- a/lib/workers/repository/extract/manager-files.spec.ts
+++ b/lib/workers/repository/extract/manager-files.spec.ts
@@ -16,7 +16,6 @@ describe('workers/repository/extract/manager-files', () => {
     let config: RenovateConfig;
 
     beforeEach(() => {
-      jest.resetAllMocks();
       config = partial<RenovateConfig>();
     });
 
diff --git a/lib/workers/repository/finalize/prune.spec.ts b/lib/workers/repository/finalize/prune.spec.ts
index 9e0a23074c..cca995e99e 100644
--- a/lib/workers/repository/finalize/prune.spec.ts
+++ b/lib/workers/repository/finalize/prune.spec.ts
@@ -14,7 +14,6 @@ jest.mock('../../../util/git');
 let config: RenovateConfig;
 
 beforeEach(() => {
-  jest.resetAllMocks();
   config = partial<RenovateConfig>({
     repoIsOnboarded: true,
     branchPrefix: `renovate/`,
diff --git a/lib/workers/repository/init/apis.spec.ts b/lib/workers/repository/init/apis.spec.ts
index 8295f41bd4..5359522d71 100644
--- a/lib/workers/repository/init/apis.spec.ts
+++ b/lib/workers/repository/init/apis.spec.ts
@@ -19,10 +19,6 @@ describe('workers/repository/init/apis', () => {
       delete config.forkProcessing;
     });
 
-    afterEach(() => {
-      jest.resetAllMocks();
-    });
-
     it('runs', async () => {
       platform.initRepo.mockResolvedValueOnce({
         defaultBranch: 'master',
diff --git a/lib/workers/repository/init/index.spec.ts b/lib/workers/repository/init/index.spec.ts
index 7681977572..4300e9231c 100644
--- a/lib/workers/repository/init/index.spec.ts
+++ b/lib/workers/repository/init/index.spec.ts
@@ -14,6 +14,10 @@ jest.mock('../init/apis');
 jest.mock('../init/config');
 jest.mock('../init/merge');
 jest.mock('../../../config/secrets');
+jest.mock('../../../modules/platform', () => ({
+  platform: { initRepo: jest.fn() },
+  getPlatformList: jest.fn(),
+}));
 
 const apis = mocked(_apis);
 const config = mocked(_config);
diff --git a/lib/workers/repository/init/merge.spec.ts b/lib/workers/repository/init/merge.spec.ts
index 7fe08d2915..5a191d4e20 100644
--- a/lib/workers/repository/init/merge.spec.ts
+++ b/lib/workers/repository/init/merge.spec.ts
@@ -34,7 +34,6 @@ let config: RenovateConfig;
 
 beforeEach(() => {
   memCache.init();
-  jest.resetAllMocks();
   config = getConfig();
   config.errors = [];
   config.warnings = [];
diff --git a/lib/workers/repository/init/vulnerability.spec.ts b/lib/workers/repository/init/vulnerability.spec.ts
index ee99bb3a14..de28fe48d9 100644
--- a/lib/workers/repository/init/vulnerability.spec.ts
+++ b/lib/workers/repository/init/vulnerability.spec.ts
@@ -7,7 +7,6 @@ import { detectVulnerabilityAlerts } from './vulnerability';
 let config: RenovateConfig;
 
 beforeEach(() => {
-  jest.resetAllMocks();
   config = getConfig();
 });
 
diff --git a/lib/workers/repository/onboarding/branch/index.spec.ts b/lib/workers/repository/onboarding/branch/index.spec.ts
index 9b8f248de9..aaecdb04bd 100644
--- a/lib/workers/repository/onboarding/branch/index.spec.ts
+++ b/lib/workers/repository/onboarding/branch/index.spec.ts
@@ -42,7 +42,6 @@ describe('workers/repository/onboarding/branch/index', () => {
 
     beforeEach(() => {
       memCache.init();
-      jest.resetAllMocks();
       config = getConfig();
       config.repository = 'some/repo';
       OnboardingState.prUpdateRequested = false;
diff --git a/lib/workers/repository/onboarding/branch/onboarding-branch-cache.spec.ts b/lib/workers/repository/onboarding/branch/onboarding-branch-cache.spec.ts
index b1e64d0a57..aabb3d30c0 100644
--- a/lib/workers/repository/onboarding/branch/onboarding-branch-cache.spec.ts
+++ b/lib/workers/repository/onboarding/branch/onboarding-branch-cache.spec.ts
@@ -251,6 +251,7 @@ describe('workers/repository/onboarding/branch/onboarding-branch-cache', () => {
     });
 
     it('returns undefined', () => {
+      cache.getCache.mockReturnValueOnce({});
       expect(getOnboardingFileNameFromCache()).toBeUndefined();
     });
   });
@@ -267,6 +268,7 @@ describe('workers/repository/onboarding/branch/onboarding-branch-cache', () => {
     });
 
     it('returns undefined', () => {
+      cache.getCache.mockReturnValueOnce({});
       expect(getOnboardingConfigFromCache()).toBeUndefined();
     });
   });
diff --git a/lib/workers/repository/onboarding/pr/base-branch.spec.ts b/lib/workers/repository/onboarding/pr/base-branch.spec.ts
index 516884c129..a499bc13d6 100644
--- a/lib/workers/repository/onboarding/pr/base-branch.spec.ts
+++ b/lib/workers/repository/onboarding/pr/base-branch.spec.ts
@@ -6,7 +6,6 @@ describe('workers/repository/onboarding/pr/base-branch', () => {
     let config: RenovateConfig;
 
     beforeEach(() => {
-      jest.resetAllMocks();
       config = partial<RenovateConfig>();
     });
 
diff --git a/lib/workers/repository/onboarding/pr/config-description.spec.ts b/lib/workers/repository/onboarding/pr/config-description.spec.ts
index 5384475673..c9144c5d7e 100644
--- a/lib/workers/repository/onboarding/pr/config-description.spec.ts
+++ b/lib/workers/repository/onboarding/pr/config-description.spec.ts
@@ -7,7 +7,6 @@ describe('workers/repository/onboarding/pr/config-description', () => {
     let config: RenovateConfig;
 
     beforeEach(() => {
-      jest.resetAllMocks();
       config = partial<RenovateConfig>();
     });
 
diff --git a/lib/workers/repository/onboarding/pr/index.spec.ts b/lib/workers/repository/onboarding/pr/index.spec.ts
index 490d9afcf2..24095e9ec0 100644
--- a/lib/workers/repository/onboarding/pr/index.spec.ts
+++ b/lib/workers/repository/onboarding/pr/index.spec.ts
@@ -29,7 +29,6 @@ describe('workers/repository/onboarding/pr/index', () => {
 
     beforeEach(() => {
       memCache.init();
-      jest.resetAllMocks();
       config = {
         ...getConfig(),
         errors: [],
@@ -38,7 +37,7 @@ describe('workers/repository/onboarding/pr/index', () => {
       };
       packageFiles = { npm: [{ packageFile: 'package.json', deps: [] }] };
       branches = [];
-      platform.massageMarkdown = jest.fn((input) => input);
+      platform.massageMarkdown.mockImplementation((input) => input);
       platform.createPr.mockResolvedValueOnce(partial<Pr>());
       GlobalConfig.reset();
     });
@@ -275,9 +274,9 @@ describe('workers/repository/onboarding/pr/index', () => {
       const err = partial<RequestError>({ response });
 
       beforeEach(() => {
-        jest.resetAllMocks();
         GlobalConfig.reset();
         scm.deleteBranch.mockResolvedValue();
+        platform.createPr.mockReset();
       });
 
       it('throws when trying to create a new PR', async () => {
diff --git a/lib/workers/repository/onboarding/pr/pr-list.spec.ts b/lib/workers/repository/onboarding/pr/pr-list.spec.ts
index 9672b38b4a..b023680ec0 100644
--- a/lib/workers/repository/onboarding/pr/pr-list.spec.ts
+++ b/lib/workers/repository/onboarding/pr/pr-list.spec.ts
@@ -7,7 +7,6 @@ describe('workers/repository/onboarding/pr/pr-list', () => {
     let config: RenovateConfig;
 
     beforeEach(() => {
-      jest.resetAllMocks();
       config = partial<RenovateConfig>({
         prHourlyLimit: 2, // default
       });
diff --git a/lib/workers/repository/process/extract-update.spec.ts b/lib/workers/repository/process/extract-update.spec.ts
index 2dc09dccfd..eadb2c2d74 100644
--- a/lib/workers/repository/process/extract-update.spec.ts
+++ b/lib/workers/repository/process/extract-update.spec.ts
@@ -30,19 +30,21 @@ jest.mock('../../../util/git');
 const branchify = mocked(_branchify);
 const repositoryCache = mocked(_repositoryCache);
 
-branchify.branchifyUpgrades.mockResolvedValue({
-  branches: [
-    {
-      manager: 'some-manager',
-      branchName: 'some-branch',
-      baseBranch: 'base',
-      upgrades: [],
-    },
-  ],
-  branchList: ['branchName'],
-});
-
 describe('workers/repository/process/extract-update', () => {
+  beforeEach(() => {
+    branchify.branchifyUpgrades.mockResolvedValue({
+      branches: [
+        {
+          manager: 'some-manager',
+          branchName: 'some-branch',
+          baseBranch: 'base',
+          upgrades: [],
+        },
+      ],
+      branchList: ['branchName'],
+    });
+  });
+
   describe('extract()', () => {
     it('runs with no baseBranches', async () => {
       const config = {
diff --git a/lib/workers/repository/process/fetch.spec.ts b/lib/workers/repository/process/fetch.spec.ts
index 5dbda35632..d701e08868 100644
--- a/lib/workers/repository/process/fetch.spec.ts
+++ b/lib/workers/repository/process/fetch.spec.ts
@@ -15,7 +15,6 @@ describe('workers/repository/process/fetch', () => {
     let config: RenovateConfig;
 
     beforeEach(() => {
-      jest.resetAllMocks();
       config = getConfig();
     });
 
diff --git a/lib/workers/repository/process/index.spec.ts b/lib/workers/repository/process/index.spec.ts
index 807a7f68e3..d6cd8c148f 100644
--- a/lib/workers/repository/process/index.spec.ts
+++ b/lib/workers/repository/process/index.spec.ts
@@ -23,7 +23,6 @@ const extract = mocked(_extractUpdate).extract;
 let config: RenovateConfig;
 
 beforeEach(() => {
-  jest.resetAllMocks();
   config = getConfig();
 });
 
diff --git a/lib/workers/repository/process/limits.spec.ts b/lib/workers/repository/process/limits.spec.ts
index a3a2e19794..26244f6ee8 100644
--- a/lib/workers/repository/process/limits.spec.ts
+++ b/lib/workers/repository/process/limits.spec.ts
@@ -7,7 +7,6 @@ import * as limits from './limits';
 let config: RenovateConfig;
 
 beforeEach(() => {
-  jest.resetAllMocks();
   config = partial<RenovateConfig>({
     branchPrefix: 'foo/',
     onboardingBranch: 'bar/configure',
diff --git a/lib/workers/repository/process/lookup/filter-checks.spec.ts b/lib/workers/repository/process/lookup/filter-checks.spec.ts
index 4541bfe3c7..c07531057f 100644
--- a/lib/workers/repository/process/lookup/filter-checks.spec.ts
+++ b/lib/workers/repository/process/lookup/filter-checks.spec.ts
@@ -43,7 +43,6 @@ describe('workers/repository/process/lookup/filter-checks', () => {
   beforeEach(() => {
     config = { currentVersion: '1.0.0' };
     sortedReleases = clone(releases);
-    jest.resetAllMocks();
     dateUtil.getElapsedMs.mockReturnValueOnce(toMs('3 days') ?? 0);
     dateUtil.getElapsedMs.mockReturnValueOnce(toMs('5 days') ?? 0);
     dateUtil.getElapsedMs.mockReturnValueOnce(toMs('7 days') ?? 0);
diff --git a/lib/workers/repository/process/lookup/index.spec.ts b/lib/workers/repository/process/lookup/index.spec.ts
index 2dfd3bbe07..a79a33241a 100644
--- a/lib/workers/repository/process/lookup/index.spec.ts
+++ b/lib/workers/repository/process/lookup/index.spec.ts
@@ -58,8 +58,6 @@ describe('workers/repository/process/lookup/index', () => {
   const getDockerDigest = jest.spyOn(DockerDatasource.prototype, 'getDigest');
 
   beforeEach(() => {
-    // TODO: fix wrong tests
-    jest.resetAllMocks();
     // TODO: fix types #22198
     config = partial<LookupUpdateConfig>(getConfig() as never);
     config.manager = 'npm';
diff --git a/lib/workers/repository/process/write.spec.ts b/lib/workers/repository/process/write.spec.ts
index 63ef3419bb..421cfbac55 100644
--- a/lib/workers/repository/process/write.spec.ts
+++ b/lib/workers/repository/process/write.spec.ts
@@ -42,7 +42,6 @@ limits.getBranchesRemaining = jest.fn().mockResolvedValue(99);
 let config: RenovateConfig;
 
 beforeEach(() => {
-  jest.resetAllMocks();
   config = getConfig();
   repoCache.getCache.mockReturnValue({});
 });
diff --git a/lib/workers/repository/result.spec.ts b/lib/workers/repository/result.spec.ts
index aced77a3d8..99b648d0b4 100644
--- a/lib/workers/repository/result.spec.ts
+++ b/lib/workers/repository/result.spec.ts
@@ -4,7 +4,6 @@ import { processResult } from './result';
 let config: RenovateConfig;
 
 beforeEach(() => {
-  jest.resetAllMocks();
   config = partial<RenovateConfig>({
     repoIsActivated: true,
     repoIsOnboarded: true,
diff --git a/lib/workers/repository/update/branch/artifacts.spec.ts b/lib/workers/repository/update/branch/artifacts.spec.ts
index 1744205fbc..dd0a321558 100644
--- a/lib/workers/repository/update/branch/artifacts.spec.ts
+++ b/lib/workers/repository/update/branch/artifacts.spec.ts
@@ -8,7 +8,6 @@ describe('workers/repository/update/branch/artifacts', () => {
 
   beforeEach(() => {
     GlobalConfig.set({});
-    jest.resetAllMocks();
     config = {
       baseBranch: 'base-branch',
       manager: 'some-manager',
diff --git a/lib/workers/repository/update/branch/auto-replace.spec.ts b/lib/workers/repository/update/branch/auto-replace.spec.ts
index 1ca2bbe6d9..3a6a1f6cf5 100644
--- a/lib/workers/repository/update/branch/auto-replace.spec.ts
+++ b/lib/workers/repository/update/branch/auto-replace.spec.ts
@@ -12,7 +12,7 @@ const sampleHtml = Fixtures.get(
   `../../../../modules/manager/html`
 );
 
-jest.mock('fs-extra', () => Fixtures.fsExtra());
+jest.mock('../../../../util/fs');
 
 describe('workers/repository/update/branch/auto-replace', () => {
   describe('doAutoReplace', () => {
diff --git a/lib/workers/repository/update/branch/automerge.spec.ts b/lib/workers/repository/update/branch/automerge.spec.ts
index 3abe8d0dd5..cc016d2647 100644
--- a/lib/workers/repository/update/branch/automerge.spec.ts
+++ b/lib/workers/repository/update/branch/automerge.spec.ts
@@ -15,6 +15,7 @@ describe('workers/repository/update/branch/automerge', () => {
     beforeEach(() => {
       config = partial<RenovateConfig>();
       GlobalConfig.reset();
+      isScheduledSpy.mockReturnValue(true);
     });
 
     it('returns false if not configured for automerge', async () => {
diff --git a/lib/workers/repository/update/branch/check-existing.spec.ts b/lib/workers/repository/update/branch/check-existing.spec.ts
index a26f611cbc..15f347deb8 100644
--- a/lib/workers/repository/update/branch/check-existing.spec.ts
+++ b/lib/workers/repository/update/branch/check-existing.spec.ts
@@ -16,7 +16,6 @@ describe('workers/repository/update/branch/check-existing', () => {
         branchName: 'some-branch',
         prTitle: 'some-title',
       } satisfies BranchConfig;
-      jest.resetAllMocks();
     });
 
     it('returns false if recreating closed PRs', async () => {
diff --git a/lib/workers/repository/update/branch/commit.spec.ts b/lib/workers/repository/update/branch/commit.spec.ts
index f98f3b57f7..df5457426e 100644
--- a/lib/workers/repository/update/branch/commit.spec.ts
+++ b/lib/workers/repository/update/branch/commit.spec.ts
@@ -20,7 +20,6 @@ describe('workers/repository/update/branch/commit', () => {
         updatedArtifacts: [],
         upgrades: [],
       } satisfies BranchConfig;
-      jest.resetAllMocks();
       scm.commitAndPush.mockResolvedValueOnce('123test');
       GlobalConfig.reset();
     });
diff --git a/lib/workers/repository/update/branch/index.spec.ts b/lib/workers/repository/update/branch/index.spec.ts
index b369aaa1ce..3a07c835ff 100644
--- a/lib/workers/repository/update/branch/index.spec.ts
+++ b/lib/workers/repository/update/branch/index.spec.ts
@@ -139,7 +139,6 @@ describe('workers/repository/update/branch/index', () => {
       platform.ensureComment.mockClear();
       platform.ensureCommentRemoval.mockClear();
       commit.commitFilesToBranch.mockClear();
-      jest.resetAllMocks();
       GlobalConfig.reset();
     });
 
diff --git a/lib/workers/repository/update/branch/lock-files/index.spec.ts b/lib/workers/repository/update/branch/lock-files/index.spec.ts
index e3d77a7e11..a5c3ea93a1 100644
--- a/lib/workers/repository/update/branch/lock-files/index.spec.ts
+++ b/lib/workers/repository/update/branch/lock-files/index.spec.ts
@@ -27,7 +27,6 @@ const { writeUpdatedPackageFiles, getAdditionalFiles } = lockFiles;
 describe('workers/repository/update/branch/lock-files/index', () => {
   describe('writeUpdatedPackageFiles', () => {
     beforeEach(() => {
-      jest.resetAllMocks();
       GlobalConfig.set({
         localDir: 'some-tmp-dir',
       });
@@ -94,10 +93,6 @@ describe('workers/repository/update/branch/lock-files/index', () => {
       jest.spyOn(lockFiles, 'determineLockFileDirs');
     });
 
-    afterEach(() => {
-      jest.resetAllMocks();
-    });
-
     it('returns no error and empty lockfiles if updateLockFiles false', async () => {
       config.updateLockFiles = false;
       const res = await getAdditionalFiles(config, { npm: [{}] });
diff --git a/lib/workers/repository/update/branch/reuse.spec.ts b/lib/workers/repository/update/branch/reuse.spec.ts
index 48363129ad..6250352edd 100644
--- a/lib/workers/repository/update/branch/reuse.spec.ts
+++ b/lib/workers/repository/update/branch/reuse.spec.ts
@@ -22,7 +22,6 @@ describe('workers/repository/update/branch/reuse', () => {
         rebaseWhen: 'behind-base-branch',
         upgrades: [],
       };
-      jest.resetAllMocks();
     });
 
     it('returns false if branch does not exist', async () => {
diff --git a/lib/workers/repository/update/branch/schedule.spec.ts b/lib/workers/repository/update/branch/schedule.spec.ts
index c7ab2bb6de..5b39e3729d 100644
--- a/lib/workers/repository/update/branch/schedule.spec.ts
+++ b/lib/workers/repository/update/branch/schedule.spec.ts
@@ -13,10 +13,6 @@ describe('workers/repository/update/branch/schedule', () => {
   });
 
   describe('hasValidSchedule(schedule)', () => {
-    beforeEach(() => {
-      jest.resetAllMocks();
-    });
-
     it('returns true for null', () => {
       expect(schedule.hasValidSchedule(null)[0]).toBeTrue();
     });
@@ -146,7 +142,7 @@ describe('workers/repository/update/branch/schedule', () => {
 
     beforeEach(() => {
       jest.setSystemTime(new Date('2017-06-30T10:50:00.000')); // Locally 2017-06-30 10:50am
-      jest.resetAllMocks();
+
       config = {};
     });
 
diff --git a/lib/workers/repository/update/branch/status-checks.spec.ts b/lib/workers/repository/update/branch/status-checks.spec.ts
index 4faeefe9c0..05dc5740d4 100644
--- a/lib/workers/repository/update/branch/status-checks.spec.ts
+++ b/lib/workers/repository/update/branch/status-checks.spec.ts
@@ -17,9 +17,7 @@ describe('workers/repository/update/branch/status-checks', () => {
       });
     });
 
-    afterEach(() => {
-      jest.resetAllMocks();
-    });
+    afterEach(() => {});
 
     it('returns if not configured', async () => {
       await setStability(config);
@@ -58,10 +56,6 @@ describe('workers/repository/update/branch/status-checks', () => {
       };
     });
 
-    afterEach(() => {
-      jest.resetAllMocks();
-    });
-
     it('returns if not configured', async () => {
       await setConfidence(config);
       expect(platform.getBranchStatusCheck).toHaveBeenCalledTimes(0);
diff --git a/lib/workers/repository/update/pr/automerge.spec.ts b/lib/workers/repository/update/pr/automerge.spec.ts
index b602de4516..71d389ad12 100644
--- a/lib/workers/repository/update/pr/automerge.spec.ts
+++ b/lib/workers/repository/update/pr/automerge.spec.ts
@@ -19,6 +19,7 @@ describe('workers/repository/update/pr/automerge', () => {
         upgrades: [],
       } satisfies BranchConfig;
       pr = partial<Pr>();
+      spy.mockReturnValue(true);
     });
 
     it('should not automerge if not configured', async () => {
diff --git a/lib/workers/repository/update/pr/body/changelogs.spec.ts b/lib/workers/repository/update/pr/body/changelogs.spec.ts
index 44c6134a36..bcdb38ebab 100644
--- a/lib/workers/repository/update/pr/body/changelogs.spec.ts
+++ b/lib/workers/repository/update/pr/body/changelogs.spec.ts
@@ -6,10 +6,6 @@ jest.mock('../../../../../util/template');
 const template = mocked(_template);
 
 describe('workers/repository/update/pr/body/changelogs', () => {
-  beforeEach(() => {
-    jest.resetAllMocks();
-  });
-
   it('returns empty string when there is no release notes', () => {
     const res = getChangelogs({
       manager: 'some-manager',
diff --git a/lib/workers/repository/update/pr/body/config-description.spec.ts b/lib/workers/repository/update/pr/body/config-description.spec.ts
index 37bba58b2c..4f86453848 100644
--- a/lib/workers/repository/update/pr/body/config-description.spec.ts
+++ b/lib/workers/repository/update/pr/body/config-description.spec.ts
@@ -10,10 +10,6 @@ describe('workers/repository/update/pr/body/config-description', () => {
       upgrades: [],
     };
 
-    beforeEach(() => {
-      jest.resetAllMocks();
-    });
-
     it('renders stopUpdating=true', () => {
       const res = getPrConfigDescription({
         ...config,
diff --git a/lib/workers/repository/update/pr/body/footer.spec.ts b/lib/workers/repository/update/pr/body/footer.spec.ts
index d95228c3e3..3b8e8de422 100644
--- a/lib/workers/repository/update/pr/body/footer.spec.ts
+++ b/lib/workers/repository/update/pr/body/footer.spec.ts
@@ -6,10 +6,6 @@ jest.mock('../../../../../util/template');
 const template = mocked(_template);
 
 describe('workers/repository/update/pr/body/footer', () => {
-  beforeEach(() => {
-    jest.resetAllMocks();
-  });
-
   it('renders empty footer', () => {
     expect(
       getPrFooter({
diff --git a/lib/workers/repository/update/pr/body/header.spec.ts b/lib/workers/repository/update/pr/body/header.spec.ts
index c032ebe8d3..4618598e95 100644
--- a/lib/workers/repository/update/pr/body/header.spec.ts
+++ b/lib/workers/repository/update/pr/body/header.spec.ts
@@ -6,10 +6,6 @@ jest.mock('../../../../../util/template');
 const template = mocked(_template);
 
 describe('workers/repository/update/pr/body/header', () => {
-  beforeEach(() => {
-    jest.resetAllMocks();
-  });
-
   it('renders empty header', () => {
     expect(
       getPrHeader({
diff --git a/lib/workers/repository/update/pr/body/notes.spec.ts b/lib/workers/repository/update/pr/body/notes.spec.ts
index 7141511fb7..730f9788a2 100644
--- a/lib/workers/repository/update/pr/body/notes.spec.ts
+++ b/lib/workers/repository/update/pr/body/notes.spec.ts
@@ -6,10 +6,6 @@ jest.mock('../../../../../util/template');
 const template = mocked(_template);
 
 describe('workers/repository/update/pr/body/notes', () => {
-  beforeEach(() => {
-    jest.resetAllMocks();
-  });
-
   it('renders notes', () => {
     template.compile.mockImplementation((x) => x);
     const res = getPrNotes({
diff --git a/lib/workers/repository/update/pr/changelog/github/index.spec.ts b/lib/workers/repository/update/pr/changelog/github/index.spec.ts
index 386e792d1b..57d01aa953 100644
--- a/lib/workers/repository/update/pr/changelog/github/index.spec.ts
+++ b/lib/workers/repository/update/pr/changelog/github/index.spec.ts
@@ -37,7 +37,6 @@ describe('workers/repository/update/pr/changelog/github/index', () => {
   afterEach(() => {
     // FIXME: add missing http mocks
     httpMock.clear(false);
-    jest.resetAllMocks();
   });
 
   describe('getChangeLogJSON', () => {
diff --git a/lib/workers/repository/update/pr/changelog/release-notes.spec.ts b/lib/workers/repository/update/pr/changelog/release-notes.spec.ts
index 9d288ee72c..dda0633eb8 100644
--- a/lib/workers/repository/update/pr/changelog/release-notes.spec.ts
+++ b/lib/workers/repository/update/pr/changelog/release-notes.spec.ts
@@ -1,3 +1,4 @@
+import { mockDeep } from 'jest-mock-extended';
 import { DateTime } from 'luxon';
 import { Fixtures } from '../../../../../../test/fixtures';
 import * as httpMock from '../../../../../../test/http-mock';
@@ -23,7 +24,7 @@ import type {
   ChangeLogResult,
 } from './types';
 
-jest.mock('../../../../../util/host-rules');
+jest.mock('../../../../../util/host-rules', () => mockDeep());
 
 const hostRules = mocked(_hostRules);
 
diff --git a/lib/workers/repository/update/pr/code-owners.spec.ts b/lib/workers/repository/update/pr/code-owners.spec.ts
index 9b57c3fa17..2b110cee78 100644
--- a/lib/workers/repository/update/pr/code-owners.spec.ts
+++ b/lib/workers/repository/update/pr/code-owners.spec.ts
@@ -12,7 +12,6 @@ describe('workers/repository/update/pr/code-owners', () => {
     let pr: Pr;
 
     beforeEach(() => {
-      jest.resetAllMocks();
       pr = mock<Pr>();
     });
 
diff --git a/lib/workers/repository/update/pr/index.spec.ts b/lib/workers/repository/update/pr/index.spec.ts
index 7a6e86eda2..6a4411f2fa 100644
--- a/lib/workers/repository/update/pr/index.spec.ts
+++ b/lib/workers/repository/update/pr/index.spec.ts
@@ -77,7 +77,6 @@ describe('workers/repository/update/pr/index', () => {
     };
 
     beforeEach(() => {
-      jest.resetAllMocks();
       GlobalConfig.reset();
       prBody.getPrBody.mockReturnValue(body);
     });
diff --git a/lib/workers/repository/update/pr/participants.spec.ts b/lib/workers/repository/update/pr/participants.spec.ts
index 723b509588..699da1190f 100644
--- a/lib/workers/repository/update/pr/participants.spec.ts
+++ b/lib/workers/repository/update/pr/participants.spec.ts
@@ -25,7 +25,6 @@ describe('workers/repository/update/pr/participants', () => {
 
   beforeEach(() => {
     GlobalConfig.reset();
-    jest.resetAllMocks();
   });
 
   describe('assignees', () => {
diff --git a/lib/workers/repository/updates/branchify.spec.ts b/lib/workers/repository/updates/branchify.spec.ts
index 99c0d262bb..a190b65f17 100644
--- a/lib/workers/repository/updates/branchify.spec.ts
+++ b/lib/workers/repository/updates/branchify.spec.ts
@@ -13,7 +13,6 @@ jest.mock('../changelog');
 let config: RenovateConfig;
 
 beforeEach(() => {
-  jest.resetAllMocks();
   config = getConfig();
   config.errors = [];
   config.warnings = [];
diff --git a/lib/workers/repository/updates/flatten.spec.ts b/lib/workers/repository/updates/flatten.spec.ts
index 1719437685..2be37367e4 100644
--- a/lib/workers/repository/updates/flatten.spec.ts
+++ b/lib/workers/repository/updates/flatten.spec.ts
@@ -8,7 +8,6 @@ jest.mock('../../../util/git/semantic');
 let config: RenovateConfig;
 
 beforeEach(() => {
-  jest.resetAllMocks();
   config = getConfig();
   config.errors = [];
   config.warnings = [];
diff --git a/lib/workers/repository/updates/generate.spec.ts b/lib/workers/repository/updates/generate.spec.ts
index 359fc85ce4..d47c2eb607 100644
--- a/lib/workers/repository/updates/generate.spec.ts
+++ b/lib/workers/repository/updates/generate.spec.ts
@@ -15,7 +15,6 @@ const {
 let requiredDefaultOptions = {};
 
 beforeEach(() => {
-  jest.resetAllMocks();
   requiredDefaultOptions = {
     commitMessage,
     commitMessagePrefix,
diff --git a/test/fixtures.ts b/test/fixtures.ts
index a63fe8c415..baa9aefe44 100644
--- a/test/fixtures.ts
+++ b/test/fixtures.ts
@@ -1,13 +1,11 @@
 import fs from 'node:fs';
 import type { PathLike, Stats } from 'node:fs';
-import { jest } from '@jest/globals';
 import callsite from 'callsite';
 import { DirectoryJSON, fs as memfs, vol } from 'memfs';
 import type { TDataOut } from 'memfs/lib/encoding';
 import upath from 'upath';
 
-// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
-const realFs = jest.requireActual('fs') as typeof fs;
+const realFs = fs; //jest.requireActual<typeof fs>('fs');
 
 /**
  * Class to work with in-memory file-system
@@ -86,19 +84,12 @@ export class Fixtures {
    */
   static reset(): void {
     vol.reset();
-  }
-
-  // Temporary solution, when all tests will be rewritten to Fixtures mocks can be moved into __mocks__ folder
-  static fsExtra(): any {
-    return {
-      ...memfs,
-      pathExists: jest.fn(pathExists),
-      remove: jest.fn(memfs.promises.rm),
-      readFile: jest.fn(readFile),
-      writeFile: jest.fn(memfs.promises.writeFile),
-      outputFile: jest.fn(outputFile),
-      stat: jest.fn(stat),
-    };
+    fsExtraMock.pathExists.mockImplementation(pathExists);
+    fsExtraMock.remove.mockImplementation(memfs.promises.rm);
+    fsExtraMock.readFile.mockImplementation(readFile);
+    fsExtraMock.writeFile.mockImplementation(memfs.promises.writeFile);
+    fsExtraMock.outputFile.mockImplementation(outputFile);
+    fsExtraMock.stat.mockImplementation(stat);
   }
 
   private static getPathToFixtures(fixturesRoot = '.'): string {
@@ -108,6 +99,23 @@ export class Fixtures {
   }
 }
 
+const fsExtraMock = {
+  pathExists: jest.fn(),
+  remove: jest.fn(),
+  readFile: jest.fn(),
+  writeFile: jest.fn(),
+  outputFile: jest.fn(),
+  stat: jest.fn(),
+};
+
+// Temporary solution, when all tests will be rewritten to Fixtures mocks can be moved into __mocks__ folder
+export function fsExtra(): any {
+  return {
+    ...memfs,
+    ...fsExtraMock,
+  };
+}
+
 export function readFile(fileName: string, options: any): Promise<TDataOut> {
   if (fileName.endsWith('.wasm') || fileName.endsWith('.wasm.gz')) {
     return fs.promises.readFile(fileName, options);
diff --git a/test/setup.ts b/test/setup.ts
index 4d9ccd34d5..4ee0a3ca97 100644
--- a/test/setup.ts
+++ b/test/setup.ts
@@ -1,173 +1,16 @@
-import type { Jest } from '@jest/environment';
 // Check for missing or pending http mocks
 import './http-mock';
-import type { Global } from '@jest/types';
-import type { AsymmetricMatchers, BaseExpect, Matchers } from 'expect';
-import type {
-  ClassLike,
-  FunctionLike,
-  MockInstance as JestMockInstance,
-  Mocked as JestMocked,
-  MockedClass as JestMockedClass,
-  MockedFunction as JestMockedFunction,
-  MockedObject as JestMockedObject,
-  SpyInstance as JestSpyInstance,
-} from 'jest-mock';
 import { mockDeep } from 'jest-mock-extended';
-import type { SnapshotMatchers } from 'jest-snapshot';
-import type { Plugin } from 'pretty-format';
-import type { PlatformScm } from '../lib/modules/platform';
+import type { Platform, PlatformScm } from '../lib/modules/platform';
 
 jest.mock('../lib/modules/platform', () => ({
-  platform: jest.createMockFromModule('../lib/modules/platform/github'),
+  platform: mockDeep<Platform>(),
   initPlatform: jest.fn(),
   getPlatformList: jest.fn(),
 }));
+
 jest.mock('../lib/modules/platform/scm', () => ({
   scm: mockDeep<PlatformScm>(),
 }));
 
-jest.mock('../lib/logger', () => jest.createMockFromModule('../lib/logger'));
-
-//------------------------------------------------
-// Required global jest types
-//------------------------------------------------
-declare global {
-  // Extension point for jest matchers
-  type JestMatchers<R, T = any> = jest.Matchers<R> &
-    SnapshotMatchers<R extends void | Promise<void> ? R : void, T> &
-    Omit<
-      Matchers<R extends void | Promise<void> ? R : void>,
-      'toMatchObject'
-    > & {
-      // TODO: override, because type issues (#22198)
-      /**
-       * Used to check that a JavaScript object matches a subset of the properties of an object
-       *
-       * Optionally, you can provide an object to use as Generic type for the expected value.
-       * This ensures that the matching object matches the structure of the provided object-like type.
-       *
-       * @example
-       *
-       * type House = {
-       *   bath: boolean;
-       *   bedrooms: number;
-       *   kitchen: {
-       *     amenities: string[];
-       *     area: number;
-       *     wallColor: string;
-       *   }
-       * };
-       *
-       * expect(desiredHouse).toMatchObject<House>({...standardHouse, kitchen: {area: 20}}) // wherein standardHouse is some base object of type House
-       */
-      toMatchObject<E extends object | any[]>(
-        expected: E
-      ): R extends void | Promise<void> ? R : void;
-    };
-}
-
-type JestInverse<Matchers> = {
-  /**
-   * Inverse next matcher. If you know how to test something, `.not` lets you test its opposite.
-   */
-  not: Matchers;
-};
-
-type JestPromiseMatchers<T> = {
-  /**
-   * Unwraps the reason of a rejected promise so any other matcher can be chained.
-   * If the promise is fulfilled the assertion fails.
-   */
-  rejects: JestMatchers<Promise<void>, T> &
-    JestInverse<JestMatchers<Promise<void>, T>>;
-  /**
-   * Unwraps the value of a fulfilled promise so any other matcher can be chained.
-   * If the promise is rejected the assertion fails.
-   */
-  resolves: JestMatchers<Promise<void>, T> &
-    JestInverse<JestMatchers<Promise<void>, T>>;
-};
-
-type JestExpect = {
-  <T = unknown>(actual: T): JestMatchers<void, T> &
-    JestInverse<JestMatchers<void, T>> &
-    JestPromiseMatchers<T>;
-  addSnapshotSerializer: (arg: Plugin) => void;
-} & BaseExpect &
-  AsymmetricMatchers &
-  JestInverse<Omit<AsymmetricMatchers, 'any' | 'anything'>> &
-  jest.Expect;
-
-type JestItEach = Global.It['each'];
-
-interface JestEach extends JestItEach {
-  (strings: TemplateStringsArray, ...placeholders: any[]): (
-    name: string,
-    fn: (arg: any) => ReturnType<Global.TestFn>,
-    timeout?: number
-  ) => void;
-}
-
-interface JestIt extends Global.It {
-  // TODO: override, because type issues (#22198)
-  each: JestEach;
-}
-
-declare global {
-  const afterAll: Global.HookBase;
-  const afterEach: Global.HookBase;
-  const beforeAll: Global.HookBase;
-  const beforeEach: Global.HookBase;
-  const describe: Global.Describe;
-  const expect: JestExpect;
-  const it: JestIt;
-  const jest: Omit<Jest, 'fn'> & {
-    // TODO: override, because type issues (#22198)
-    fn(): jest.Mock;
-    fn<T, Y extends any[]>(implementation?: (...args: Y) => T): jest.Mock<T, Y>;
-  };
-  const test: JestIt;
-
-  // eslint-disable-next-line @typescript-eslint/no-namespace
-  namespace jest {
-    /**
-     * Wraps a class, function or object type with Jest mock type definitions.
-     */
-    type Mocked<T extends object> = JestMocked<T>;
-    /**
-     * Wraps a class type with Jest mock type definitions.
-     */
-    type MockedClass<T extends ClassLike> = JestMockedClass<T>;
-    /**
-     * Wraps a function type with Jest mock type definitions.
-     */
-    type MockedFunction<T extends FunctionLike> = JestMockedFunction<T>;
-    /**
-     * Wraps an object type with Jest mock type definitions.
-     */
-    type MockedObject<T extends object> = JestMockedObject<T>;
-
-    type MockInstance<T, Y extends any[]> = JestMockInstance<(...args: Y) => T>;
-
-    interface Mock<T = any, Y extends any[] = any>
-      extends Function, // eslint-disable-line @typescript-eslint/ban-types
-        MockInstance<T, Y> {
-      new (...args: Y): T;
-      (...args: Y): T;
-    }
-
-    interface CustomMatcherResult {
-      pass: boolean;
-      message: string | (() => string);
-    }
-
-    type SpyInstance<T, Y extends any[]> = JestSpyInstance<(...args: Y) => T>;
-
-    // Extension point for jest matchers
-    interface Expect {}
-    // Extension point for jest matchers
-    // eslint-disable-next-line @typescript-eslint/no-unused-vars
-    interface Matchers<R> {}
-  }
-}
+jest.mock('../lib/logger', () => mockDeep());
diff --git a/test/types/jest.d.ts b/test/types/jest.d.ts
new file mode 100644
index 0000000000..9a6df8a048
--- /dev/null
+++ b/test/types/jest.d.ts
@@ -0,0 +1,156 @@
+import type { AsymmetricMatchers, BaseExpect, Matchers } from 'expect';
+import type { SnapshotMatchers } from 'jest-snapshot';
+import type { Global } from '@jest/types';
+import type { Jest } from '@jest/environment';
+import type {
+  ClassLike,
+  FunctionLike,
+  MockInstance as JestMockInstance,
+  Mocked as JestMocked,
+  MockedClass as JestMockedClass,
+  MockedFunction as JestMockedFunction,
+  MockedObject as JestMockedObject,
+  SpyInstance as JestSpyInstance,
+} from 'jest-mock';
+
+//------------------------------------------------
+// Required global jest types
+//------------------------------------------------
+declare global {
+  // Extension point for jest matchers
+  type JestMatchers<R, T = any> = jest.Matchers<R> &
+    SnapshotMatchers<R extends void | Promise<void> ? R : void, T> &
+    Omit<
+      Matchers<R extends void | Promise<void> ? R : void>,
+      'toMatchObject'
+    > & {
+      // TODO: override, because type issues (#22198)
+      /**
+       * Used to check that a JavaScript object matches a subset of the properties of an object
+       *
+       * Optionally, you can provide an object to use as Generic type for the expected value.
+       * This ensures that the matching object matches the structure of the provided object-like type.
+       *
+       * @example
+       *
+       * type House = {
+       *   bath: boolean;
+       *   bedrooms: number;
+       *   kitchen: {
+       *     amenities: string[];
+       *     area: number;
+       *     wallColor: string;
+       *   }
+       * };
+       *
+       * expect(desiredHouse).toMatchObject<House>({...standardHouse, kitchen: {area: 20}}) // wherein standardHouse is some base object of type House
+       */
+      toMatchObject<E extends object | any[]>(
+        expected: E
+      ): R extends void | Promise<void> ? R : void;
+    };
+}
+
+type JestInverse<Matchers> = {
+  /**
+   * Inverse next matcher. If you know how to test something, `.not` lets you test its opposite.
+   */
+  not: Matchers;
+};
+
+type JestPromiseMatchers<T> = {
+  /**
+   * Unwraps the reason of a rejected promise so any other matcher can be chained.
+   * If the promise is fulfilled the assertion fails.
+   */
+  rejects: JestMatchers<Promise<void>, T> &
+    JestInverse<JestMatchers<Promise<void>, T>>;
+  /**
+   * Unwraps the value of a fulfilled promise so any other matcher can be chained.
+   * If the promise is rejected the assertion fails.
+   */
+  resolves: JestMatchers<Promise<void>, T> &
+    JestInverse<JestMatchers<Promise<void>, T>>;
+};
+
+type JestExpect = {
+  <T = unknown>(actual: T): JestMatchers<void, T> &
+    JestInverse<JestMatchers<void, T>> &
+    JestPromiseMatchers<T>;
+  addSnapshotSerializer: (arg: Plugin) => void;
+} & BaseExpect &
+  AsymmetricMatchers &
+  JestInverse<Omit<AsymmetricMatchers, 'any' | 'anything'>> &
+  jest.Expect;
+
+type JestItEach = Global.It['each'];
+
+interface JestEach extends JestItEach {
+  (strings: TemplateStringsArray, ...placeholders: any[]): (
+    name: string,
+    fn: (arg: any) => ReturnType<Global.TestFn>,
+    timeout?: number
+  ) => void;
+}
+
+interface JestIt extends Global.It {
+  // TODO: override, because type issues (#22198)
+  each: JestEach;
+}
+
+declare global {
+  const afterAll: Global.HookBase;
+  const afterEach: Global.HookBase;
+  const beforeAll: Global.HookBase;
+  const beforeEach: Global.HookBase;
+  const describe: Global.Describe;
+  const expect: JestExpect;
+  const it: JestIt;
+  var jest: Omit<Jest, 'fn'> & {
+    // TODO: override, because type issues (#22198)
+    fn(): jest.Mock;
+    fn<T, Y extends any[]>(implementation?: (...args: Y) => T): jest.Mock<T, Y>;
+  };
+  const test: JestIt;
+
+  namespace jest {
+    /**
+     * Wraps a class, function or object type with Jest mock type definitions.
+     */
+    type Mocked<T extends object> = JestMocked<T>;
+    /**
+     * Wraps a class type with Jest mock type definitions.
+     */
+    type MockedClass<T extends ClassLike> = JestMockedClass<T>;
+    /**
+     * Wraps a function type with Jest mock type definitions.
+     */
+    type MockedFunction<T extends FunctionLike> = JestMockedFunction<T>;
+    /**
+     * Wraps an object type with Jest mock type definitions.
+     */
+    type MockedObject<T extends object> = JestMockedObject<T>;
+
+    type MockInstance<T, Y extends any[]> = JestMockInstance<(...args: Y) => T>;
+
+    interface Mock<T = any, Y extends any[] = any>
+      extends Function, // eslint-disable-line @typescript-eslint/ban-types
+        MockInstance<T, Y> {
+      new (...args: Y): T;
+      (...args: Y): T;
+    }
+
+    interface CustomMatcherResult {
+      pass: boolean;
+      message: string | (() => string);
+    }
+
+    type SpyInstance<T, Y extends any[]> = JestSpyInstance<(...args: Y) => T>;
+
+    // Extension point for jest matchers
+    interface Expect {}
+
+    // Extension point for jest matchers
+    interface Matchers<R> {}
+  }
+}
diff --git a/test/util.ts b/test/util.ts
index a3189ac255..bb02d434fd 100644
--- a/test/util.ts
+++ b/test/util.ts
@@ -16,8 +16,8 @@ import { regEx } from '../lib/util/regex';
  * Simple wrapper for getting mocked version of a module
  * @param module module which is mocked by `jest.mock`
  */
-export function mocked<T extends object>(module: T): jest.MockedObject<T> {
-  return module as jest.MockedObject<T>;
+export function mocked<T extends object>(module: T): jest.Mocked<T> {
+  return jest.mocked(module);
 }
 
 /**
@@ -41,15 +41,15 @@ export function partial(obj: unknown = {}): unknown {
   return obj;
 }
 
-export const fs = mocked(_fs);
-export const git = mocked(_git);
+export const fs = jest.mocked(_fs);
+export const git = jest.mocked(_git);
 
 // TODO: fix types, jest / typescript is using wrong overload (#22198)
-export const platform = mocked(partial<Required<Platform>>(_platform));
-export const scm = mocked(_scm);
-export const env = mocked(_env);
-export const hostRules = mocked(_hostRules);
-export const logger = mocked(_logger);
+export const platform = jest.mocked(partial<Required<Platform>>(_platform));
+export const scm = jest.mocked(_scm);
+export const env = jest.mocked(_env);
+export const hostRules = jest.mocked(_hostRules);
+export const logger = jest.mocked(_logger);
 
 export type { RenovateConfig };
 
-- 
GitLab