diff --git a/CHANGELOG.md b/CHANGELOG.md
index 47532a7c064..43d327b57f4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -45,6 +45,11 @@
## Apollo Client 3.4.11 (not yet released)
+### Improvements
+
+- Make `@apollo/client/testing` a fully-fledged, independent entry point, instead of re-exporting `@apollo/client/utilities/testing` (which was never an entry point and no longer exists).
+ [@benjamn](https://github.com/benjamn) in [#8769](https://github.com/apollographql/apollo-client/pull/8769)
+
### Bug Fixes
- Fix [Vite](https://vitejs.dev) tree-shaking by calling the `checkDEV()` function (at least once) in the module that exports it, `@apollo/client/utilities/globals/index.ts`.
diff --git a/config/entryPoints.js b/config/entryPoints.js
index 9986e2d68f1..9873a8a12c1 100644
--- a/config/entryPoints.js
+++ b/config/entryPoints.js
@@ -21,9 +21,9 @@ const entryPoints = [
{ dirs: ['react', 'hooks'] },
{ dirs: ['react', 'parser'] },
{ dirs: ['react', 'ssr'] },
+ { dirs: ['testing'], extensions: [".js", ".jsx"] },
{ dirs: ['utilities'] },
{ dirs: ['utilities', 'globals'], sideEffects: true },
- { dirs: ['testing'], extensions: [".js", ".jsx"] },
];
const lookupTrie = Object.create(null);
diff --git a/src/__tests__/local-state/resolvers.ts b/src/__tests__/local-state/resolvers.ts
index 8c384b7c547..3a35cffadca 100644
--- a/src/__tests__/local-state/resolvers.ts
+++ b/src/__tests__/local-state/resolvers.ts
@@ -15,8 +15,8 @@ import { InMemoryCache } from '../../cache';
import { Observable, Observer } from '../../utilities';
import { ApolloLink } from '../../link/core';
import { itAsync } from '../../testing';
-import mockQueryManager from '../../utilities/testing/mocking/mockQueryManager';
-import wrap from '../../utilities/testing/wrap';
+import mockQueryManager from '../../testing/mocking/mockQueryManager';
+import wrap from '../../testing/wrap';
// Helper method that sets up a mockQueryManager and then passes on the
// results to an observer.
diff --git a/src/__tests__/refetchQueries.ts b/src/__tests__/refetchQueries.ts
index a18f8f5a861..2fefb40e4aa 100644
--- a/src/__tests__/refetchQueries.ts
+++ b/src/__tests__/refetchQueries.ts
@@ -1,6 +1,6 @@
import { Subscription } from "zen-observable-ts";
-import { itAsync } from '../utilities/testing/itAsync';
+import { itAsync } from '../testing/itAsync';
import {
ApolloClient,
ApolloLink,
diff --git a/src/cache/inmemory/__tests__/policies.ts b/src/cache/inmemory/__tests__/policies.ts
index 3fc63c4f483..101bb09e6fa 100644
--- a/src/cache/inmemory/__tests__/policies.ts
+++ b/src/cache/inmemory/__tests__/policies.ts
@@ -5,9 +5,9 @@ import { ReactiveVar, makeVar } from "../reactiveVars";
import { Reference, StoreObject, ApolloClient, NetworkStatus, TypedDocumentNode, DocumentNode } from "../../../core";
import { MissingFieldError } from "../..";
import { relayStylePagination } from "../../../utilities";
-import { MockLink } from '../../../utilities/testing/mocking/mockLink';
-import subscribeAndCount from '../../../utilities/testing/subscribeAndCount';
-import { itAsync } from '../../../utilities/testing/itAsync';
+import { MockLink } from '../../../testing/mocking/mockLink';
+import subscribeAndCount from '../../../testing/subscribeAndCount';
+import { itAsync } from '../../../testing/itAsync';
import { FieldPolicy, StorageType } from "../policies";
import { withErrorSpy, withWarningSpy } from "../../../testing";
diff --git a/src/cache/inmemory/__tests__/writeToStore.ts b/src/cache/inmemory/__tests__/writeToStore.ts
index ae3817ec0b9..2ac38fb9f9b 100644
--- a/src/cache/inmemory/__tests__/writeToStore.ts
+++ b/src/cache/inmemory/__tests__/writeToStore.ts
@@ -18,7 +18,7 @@ import {
} from '../../../utilities/graphql/storeUtils';
import { addTypenameToDocument } from '../../../utilities/graphql/transform';
import { cloneDeep } from '../../../utilities/common/cloneDeep';
-import { itAsync } from '../../../utilities/testing/itAsync';
+import { itAsync } from '../../../testing/itAsync';
import { StoreWriter } from '../writeToStore';
import { defaultNormalizedCacheFactory, writeQueryToStore } from './helpers';
import { InMemoryCache } from '../inMemoryCache';
diff --git a/src/core/__tests__/ObservableQuery.ts b/src/core/__tests__/ObservableQuery.ts
index 45abeaa2ebe..09cd7a6efa0 100644
--- a/src/core/__tests__/ObservableQuery.ts
+++ b/src/core/__tests__/ObservableQuery.ts
@@ -12,9 +12,9 @@ import { InMemoryCache, NormalizedCacheObject } from '../../cache';
import { ApolloError } from '../../errors';
import { itAsync, mockSingleLink, subscribeAndCount } from '../../testing';
-import mockQueryManager from '../../utilities/testing/mocking/mockQueryManager';
-import mockWatchQuery from '../../utilities/testing/mocking/mockWatchQuery';
-import wrap from '../../utilities/testing/wrap';
+import mockQueryManager from '../../testing/mocking/mockQueryManager';
+import mockWatchQuery from '../../testing/mocking/mockWatchQuery';
+import wrap from '../../testing/wrap';
export const mockFetchQuery = (queryManager: QueryManager) => {
const fetchQueryObservable = queryManager.fetchQueryObservable;
diff --git a/src/core/__tests__/QueryManager/index.ts b/src/core/__tests__/QueryManager/index.ts
index 1342260f38f..e6a002994f0 100644
--- a/src/core/__tests__/QueryManager/index.ts
+++ b/src/core/__tests__/QueryManager/index.ts
@@ -15,9 +15,9 @@ import {
} from '../../../cache/inmemory/types';
// mocks
-import mockQueryManager from '../../../utilities/testing/mocking/mockQueryManager';
-import mockWatchQuery from '../../../utilities/testing/mocking/mockWatchQuery';
-import { MockApolloLink, mockSingleLink } from '../../../utilities/testing/mocking/mockLink';
+import mockQueryManager from '../../../testing/mocking/mockQueryManager';
+import mockWatchQuery from '../../../testing/mocking/mockWatchQuery';
+import { MockApolloLink, mockSingleLink } from '../../../testing/mocking/mockLink';
// core
import { ApolloQueryResult } from '../../types';
@@ -29,12 +29,12 @@ import { QueryManager } from '../../QueryManager';
import { ApolloError } from '../../../errors';
// testing utils
-import wrap from '../../../utilities/testing/wrap';
+import wrap from '../../../testing/wrap';
import observableToPromise, {
observableToPromiseAndSubscription,
-} from '../../../utilities/testing/observableToPromise';
-import subscribeAndCount from '../../../utilities/testing/subscribeAndCount';
-import { itAsync } from '../../../utilities/testing/itAsync';
+} from '../../../testing/observableToPromise';
+import subscribeAndCount from '../../../testing/subscribeAndCount';
+import { itAsync } from '../../../testing/itAsync';
import { ApolloClient } from '../../../core'
import { mockFetchQuery } from '../ObservableQuery';
diff --git a/src/core/__tests__/QueryManager/links.ts b/src/core/__tests__/QueryManager/links.ts
index e3024e75312..ca0ca2aa3f0 100644
--- a/src/core/__tests__/QueryManager/links.ts
+++ b/src/core/__tests__/QueryManager/links.ts
@@ -6,7 +6,7 @@ import { ApolloLink } from '../../../link/core';
import { InMemoryCache } from '../../../cache/inmemory/inMemoryCache';
// mocks
-import { MockSubscriptionLink } from '../../../utilities/testing/mocking/mockSubscriptionLink';
+import { MockSubscriptionLink } from '../../../testing/mocking/mockSubscriptionLink';
// core
import { QueryManager } from '../../QueryManager';
diff --git a/src/core/__tests__/QueryManager/multiple-results.ts b/src/core/__tests__/QueryManager/multiple-results.ts
index 98a2cf31415..c2925a5574e 100644
--- a/src/core/__tests__/QueryManager/multiple-results.ts
+++ b/src/core/__tests__/QueryManager/multiple-results.ts
@@ -5,7 +5,7 @@ import { InMemoryCache } from '../../../cache/inmemory/inMemoryCache';
// mocks
import {
MockSubscriptionLink
-} from '../../../utilities/testing/mocking/mockSubscriptionLink';
+} from '../../../testing/mocking/mockSubscriptionLink';
// core
import { QueryManager } from '../../QueryManager';
diff --git a/src/core/__tests__/QueryManager/recycler.ts b/src/core/__tests__/QueryManager/recycler.ts
index 0a02cee0966..9f7804bb372 100644
--- a/src/core/__tests__/QueryManager/recycler.ts
+++ b/src/core/__tests__/QueryManager/recycler.ts
@@ -9,7 +9,7 @@ import gql from 'graphql-tag';
import { InMemoryCache } from '../../../cache/inmemory/inMemoryCache';
import {
MockSubscriptionLink
-} from '../../../utilities/testing/mocking/mockSubscriptionLink';
+} from '../../../testing/mocking/mockSubscriptionLink';
// core
import { QueryManager } from '../../QueryManager';
diff --git a/src/react/hoc/__tests__/mutations/lifecycle.test.tsx b/src/react/hoc/__tests__/mutations/lifecycle.test.tsx
index 4834da4324b..7e45728ea19 100644
--- a/src/react/hoc/__tests__/mutations/lifecycle.test.tsx
+++ b/src/react/hoc/__tests__/mutations/lifecycle.test.tsx
@@ -3,7 +3,7 @@ import { render, cleanup } from '@testing-library/react';
import gql from 'graphql-tag';
import { ApolloProvider } from '../../../context/ApolloProvider';
-import { createMockClient } from '../../../../utilities/testing/mocking/mockClient';
+import { createMockClient } from '../../../../testing/mocking/mockClient';
import { graphql } from '../../graphql';
import { ChildProps } from '../../types';
diff --git a/src/testing/index.ts b/src/testing/index.ts
index b6040c34513..0547d9cb4da 100644
--- a/src/testing/index.ts
+++ b/src/testing/index.ts
@@ -1,2 +1,16 @@
import '../utilities/globals';
-export * from '../utilities/testing';
+export { MockedProvider, MockedProviderProps } from './mocking/MockedProvider';
+export {
+ MockLink,
+ mockSingleLink,
+ MockedResponse,
+ ResultFunction
+} from './mocking/mockLink';
+export {
+ MockSubscriptionLink,
+ mockObservableLink
+} from './mocking/mockSubscriptionLink';
+export { createMockClient } from './mocking/mockClient';
+export { default as subscribeAndCount } from './subscribeAndCount';
+export { itAsync } from './itAsync';
+export * from './withConsoleSpy';
diff --git a/src/utilities/testing/itAsync.ts b/src/testing/itAsync.ts
similarity index 100%
rename from src/utilities/testing/itAsync.ts
rename to src/testing/itAsync.ts
diff --git a/src/utilities/testing/mocking/MockedProvider.tsx b/src/testing/mocking/MockedProvider.tsx
similarity index 83%
rename from src/utilities/testing/mocking/MockedProvider.tsx
rename to src/testing/mocking/MockedProvider.tsx
index 819b5cb1057..2143ed41868 100644
--- a/src/utilities/testing/mocking/MockedProvider.tsx
+++ b/src/testing/mocking/MockedProvider.tsx
@@ -1,12 +1,12 @@
import * as React from 'react';
-import { ApolloClient, DefaultOptions } from '../../../core';
-import { InMemoryCache as Cache } from '../../../cache';
-import { ApolloProvider } from '../../../react/context';
+import { ApolloClient, DefaultOptions } from '../../core';
+import { InMemoryCache as Cache } from '../../cache';
+import { ApolloProvider } from '../../react/context';
import { MockLink, MockedResponse } from './mockLink';
-import { ApolloLink } from '../../../link/core';
-import { Resolvers } from '../../../core';
-import { ApolloCache } from '../../../cache';
+import { ApolloLink } from '../../link/core';
+import { Resolvers } from '../../core';
+import { ApolloCache } from '../../cache';
export interface MockedProviderProps {
mocks?: ReadonlyArray;
diff --git a/src/utilities/testing/mocking/__tests__/MockedProvider.test.tsx b/src/testing/mocking/__tests__/MockedProvider.test.tsx
similarity index 98%
rename from src/utilities/testing/mocking/__tests__/MockedProvider.test.tsx
rename to src/testing/mocking/__tests__/MockedProvider.test.tsx
index 17173541017..bb1e4e128f1 100644
--- a/src/utilities/testing/mocking/__tests__/MockedProvider.test.tsx
+++ b/src/testing/mocking/__tests__/MockedProvider.test.tsx
@@ -6,9 +6,9 @@ import { itAsync } from '../../itAsync';
import { MockedProvider } from '../MockedProvider';
import { MockedResponse, MockLink } from '../mockLink';
import { DocumentNode } from 'graphql';
-import { useQuery } from '../../../../react/hooks/useQuery';
-import { InMemoryCache } from '../../../../cache/inmemory/inMemoryCache';
-import { ApolloLink } from '../../../../link/core';
+import { useQuery } from '../../../react/hooks';
+import { InMemoryCache } from '../../../cache';
+import { ApolloLink } from '../../../link/core';
const variables = {
username: 'mock_username'
diff --git a/src/utilities/testing/mocking/__tests__/__snapshots__/MockedProvider.test.tsx.snap b/src/testing/mocking/__tests__/__snapshots__/MockedProvider.test.tsx.snap
similarity index 100%
rename from src/utilities/testing/mocking/__tests__/__snapshots__/MockedProvider.test.tsx.snap
rename to src/testing/mocking/__tests__/__snapshots__/MockedProvider.test.tsx.snap
diff --git a/src/utilities/testing/mocking/__tests__/mockSubscriptionLink.test.tsx b/src/testing/mocking/__tests__/mockSubscriptionLink.test.tsx
similarity index 87%
rename from src/utilities/testing/mocking/__tests__/mockSubscriptionLink.test.tsx
rename to src/testing/mocking/__tests__/mockSubscriptionLink.test.tsx
index ff7bca2dd67..4e7ee3fe9c7 100644
--- a/src/utilities/testing/mocking/__tests__/mockSubscriptionLink.test.tsx
+++ b/src/testing/mocking/__tests__/mockSubscriptionLink.test.tsx
@@ -3,10 +3,10 @@ import { render, wait } from '@testing-library/react';
import gql from 'graphql-tag';
import { MockSubscriptionLink } from '../mockSubscriptionLink';
-import { ApolloClient } from '../../../../core';
-import { InMemoryCache as Cache } from '../../../../cache';
-import { ApolloProvider } from '../../../../react/context';
-import { useSubscription } from '../../../../react/hooks';
+import { ApolloClient } from '../../../core';
+import { InMemoryCache as Cache } from '../../../cache';
+import { ApolloProvider } from '../../../react/context';
+import { useSubscription } from '../../../react/hooks';
describe('mockSubscriptionLink', () => {
it('should work with multiple subscribers to the same mock websocket', () => {
diff --git a/src/utilities/testing/mocking/mockClient.ts b/src/testing/mocking/mockClient.ts
similarity index 79%
rename from src/utilities/testing/mocking/mockClient.ts
rename to src/testing/mocking/mockClient.ts
index f68d719b898..cd08b891c7f 100644
--- a/src/utilities/testing/mocking/mockClient.ts
+++ b/src/testing/mocking/mockClient.ts
@@ -1,7 +1,7 @@
import { DocumentNode } from 'graphql';
-import { ApolloClient } from '../../../core';
-import { InMemoryCache, NormalizedCacheObject } from '../../../cache';
+import { ApolloClient } from '../../core';
+import { InMemoryCache, NormalizedCacheObject } from '../../cache';
import { mockSingleLink } from './mockLink';
export function createMockClient(
diff --git a/src/utilities/testing/mocking/mockFetch.ts b/src/testing/mocking/mockFetch.ts
similarity index 100%
rename from src/utilities/testing/mocking/mockFetch.ts
rename to src/testing/mocking/mockFetch.ts
diff --git a/src/utilities/testing/mocking/mockLink.ts b/src/testing/mocking/mockLink.ts
similarity index 98%
rename from src/utilities/testing/mocking/mockLink.ts
rename to src/testing/mocking/mockLink.ts
index 765fe28d319..eacab3e4876 100644
--- a/src/utilities/testing/mocking/mockLink.ts
+++ b/src/testing/mocking/mockLink.ts
@@ -1,4 +1,4 @@
-import { invariant } from '../../globals';
+import { invariant } from '../../utilities/globals';
import { print } from 'graphql';
import { equal } from '@wry/equality';
@@ -8,7 +8,7 @@ import {
Operation,
GraphQLRequest,
FetchResult,
-} from '../../../link/core';
+} from '../../link/core';
import {
Observable,
@@ -17,7 +17,7 @@ import {
removeConnectionDirectiveFromDocument,
cloneDeep,
stringifyForDisplay,
-} from '../../../utilities';
+} from '../../utilities';
export type ResultFunction = () => T;
diff --git a/src/utilities/testing/mocking/mockQueryManager.ts b/src/testing/mocking/mockQueryManager.ts
similarity index 76%
rename from src/utilities/testing/mocking/mockQueryManager.ts
rename to src/testing/mocking/mockQueryManager.ts
index ce2ad1aa700..bc03cffc38c 100644
--- a/src/utilities/testing/mocking/mockQueryManager.ts
+++ b/src/testing/mocking/mockQueryManager.ts
@@ -1,6 +1,6 @@
-import { QueryManager } from '../../../core/QueryManager';
+import { QueryManager } from '../../core/QueryManager';
import { mockSingleLink, MockedResponse } from './mockLink';
-import { InMemoryCache } from '../../../cache/inmemory/inMemoryCache';
+import { InMemoryCache } from '../../cache';
// Helper method for the tests that construct a query manager out of a
// a list of mocked responses for a mocked network interface.
diff --git a/src/utilities/testing/mocking/mockSubscriptionLink.ts b/src/testing/mocking/mockSubscriptionLink.ts
similarity index 93%
rename from src/utilities/testing/mocking/mockSubscriptionLink.ts
rename to src/testing/mocking/mockSubscriptionLink.ts
index 664789a3ea6..cd81604a1d4 100644
--- a/src/utilities/testing/mocking/mockSubscriptionLink.ts
+++ b/src/testing/mocking/mockSubscriptionLink.ts
@@ -1,5 +1,5 @@
-import { Observable } from '../../../utilities';
-import { ApolloLink, FetchResult, Operation } from '../../../link/core';
+import { Observable } from '../../utilities';
+import { ApolloLink, FetchResult, Operation } from '../../link/core';
export interface MockedSubscription {
request: Operation;
diff --git a/src/utilities/testing/mocking/mockWatchQuery.ts b/src/testing/mocking/mockWatchQuery.ts
similarity index 89%
rename from src/utilities/testing/mocking/mockWatchQuery.ts
rename to src/testing/mocking/mockWatchQuery.ts
index c4736fe6f0a..9285a342f39 100644
--- a/src/utilities/testing/mocking/mockWatchQuery.ts
+++ b/src/testing/mocking/mockWatchQuery.ts
@@ -1,6 +1,6 @@
import { MockedResponse } from './mockLink';
import mockQueryManager from './mockQueryManager';
-import { ObservableQuery } from '../../../core/ObservableQuery';
+import { ObservableQuery } from '../../core';
export default (
reject: (reason: any) => any,
diff --git a/src/utilities/testing/observableToPromise.ts b/src/testing/observableToPromise.ts
similarity index 93%
rename from src/utilities/testing/observableToPromise.ts
rename to src/testing/observableToPromise.ts
index 36930d5431c..10047be8512 100644
--- a/src/utilities/testing/observableToPromise.ts
+++ b/src/testing/observableToPromise.ts
@@ -1,6 +1,5 @@
-import { ObservableQuery } from '../../core/ObservableQuery';
-import { ApolloQueryResult } from '../../core/types';
-import { ObservableSubscription } from '../../utilities/observables/Observable';
+import { ObservableQuery, ApolloQueryResult } from '../core';
+import { ObservableSubscription } from '../utilities';
/**
*
diff --git a/src/utilities/testing/subscribeAndCount.ts b/src/testing/subscribeAndCount.ts
similarity index 75%
rename from src/utilities/testing/subscribeAndCount.ts
rename to src/testing/subscribeAndCount.ts
index 61589ede615..68aeb3f39c2 100644
--- a/src/utilities/testing/subscribeAndCount.ts
+++ b/src/testing/subscribeAndCount.ts
@@ -1,7 +1,5 @@
-import { ObservableQuery } from '../../core/ObservableQuery';
-import { ApolloQueryResult, OperationVariables } from '../../core/types';
-import { ObservableSubscription } from '../../utilities/observables/Observable';
-import { asyncMap } from '../../utilities/observables/asyncMap';
+import { ObservableQuery, ApolloQueryResult, OperationVariables } from '../core';
+import { ObservableSubscription, asyncMap } from '../utilities';
export default function subscribeAndCount<
TData,
diff --git a/src/utilities/testing/withConsoleSpy.ts b/src/testing/withConsoleSpy.ts
similarity index 100%
rename from src/utilities/testing/withConsoleSpy.ts
rename to src/testing/withConsoleSpy.ts
diff --git a/src/utilities/testing/wrap.ts b/src/testing/wrap.ts
similarity index 100%
rename from src/utilities/testing/wrap.ts
rename to src/testing/wrap.ts
diff --git a/src/utilities/observables/__tests__/asyncMap.ts b/src/utilities/observables/__tests__/asyncMap.ts
index f571c60c711..a40ee596272 100644
--- a/src/utilities/observables/__tests__/asyncMap.ts
+++ b/src/utilities/observables/__tests__/asyncMap.ts
@@ -1,6 +1,6 @@
-import { itAsync } from "../../testing";
import { Observable } from "../Observable";
import { asyncMap } from "../asyncMap";
+import { itAsync } from "../../../testing";
const wait = (delayMs: number) =>
new Promise(resolve => setTimeout(resolve, delayMs));
diff --git a/src/utilities/testing/index.ts b/src/utilities/testing/index.ts
deleted file mode 100644
index 8432ed8b97c..00000000000
--- a/src/utilities/testing/index.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-export { MockedProvider, MockedProviderProps } from './mocking/MockedProvider';
-export {
- MockLink,
- mockSingleLink,
- MockedResponse,
- ResultFunction
-} from './mocking/mockLink';
-export {
- MockSubscriptionLink,
- mockObservableLink
-} from './mocking/mockSubscriptionLink';
-export { createMockClient } from './mocking/mockClient';
-export { default as subscribeAndCount } from './subscribeAndCount';
-export { itAsync } from './itAsync';
-export * from './withConsoleSpy';