I have a Typescript/React Application leveraging Amplify to run in AWS.
My Application leverages Amplify API (GraphQL) and Amplify Storage for working with Amazon Services.
in Amplify V5 I was able to Set Jest Functions for the relevant API calls so I could safely run unit tests.
setupTests.ts
import {API, Storage} from "aws-amplify";
/** Establish API mocking before all tests. */
beforeAll(() => {
URL.revokeObjectURL = jest.fn();
//Window.prototype.scroll = jest.fn();
window.HTMLElement.prototype.scroll = jest.fn();
window.HTMLDivElement.prototype.scroll = jest.fn();
jest.mock('aws-amplify');
API.graphql = jest.fn();
Storage.get = jest.fn();
Storage.copy = jest.fn();
Storage.remove = jest.fn();
});
I am now upgrading from V5 to V6 of amplify. The API changed.
instead of import {API, Storage} from "aws-amplify";
and then running the functions on those objects, the functions are imported directly.
import {generateClient} from 'aws-amplify/api'
import {getUrl, downloadData, copy, remove, uploadData} from 'aws-amplify/storage';
I’ve tried a few different things to mock generateClient in setupTests.ts but nothing has worked.
jest.mock('aws-amplify');
jest.mock('aws-amplify/api');
jest.mock('aws-amplify/storage');
jest.mock('aws-amplify/api',
() => { return { generateClient: () => { graphql: jest.fn() } };
});
jest.mock('generateClient', () => { graphql: jest.fn(); });
jest.mock('aws-amplify/api', () => {
return { generateClient: () => { graphql: jest.fn() } };
});
import * as API from 'aws-amplify/api';
beforeAll(() => {
API.generateClient = jest.fn();
const generateClient = jest.mocked(API).generateClient;
const generateClient = API.generateClient;
});
jest.mocked(generateClient).mockImplementation(() => ({graphql: jest.fn()}));
jest.mock('aws-amplify/auth');
jest.mock('getUrl', () => jest.fn());
jest.mock('downloadData', () => jest.fn());
jest.mock('uploadData', () => jest.fn());
jest.mock('copy', () => jest.fn());
jest.mock('remove', () => jest.fn());
// @ts-ignore
generateClient.mockImplementation(() => ({graphql: jest.fn()}));
// @ts-ignore
getUrl.mockImplementation(() => {});
// @ts-ignore
downloadData.mockImplementation(() => {});
// @ts-ignore
uploadData.mockImplementation(() => {});
// @ts-ignore
copy.mockImplementation(() => {});
// @ts-ignore
remove.mockImplementation(() => {});
When testing with
expect(client.graphql).not.toHaveBeenCalled();
where client = generateClient();
and was either later on in the same beforeAll
method or a separate test file. I kept getting errors that client.graphQL
is an actual function and not a mock, in the case of the *.mockImplementation()
example the error was about that function not being available, because the code wasn’t mocked yet.
TL/DR: In Amplify V6, with the direct method, and generator Exports, how do I setup my tests to just Jest Mock Functions in place of the real calls in my production code for unit testing?