Writing unit tests of your code using jest and axios with adapters can be quite challenging. Using typescript, you might get this error TypeError: Cannot read properties of undefined(reading 'get')
.
In this example, I’m using axios-cache-adapter like this:
You can mock your axios component this way (axios.ts
):
import axios from 'axios'
import { IAxiosCacheAdapterOptions, setupCache } from 'axios-cache-adapter'
// extending Axios type to fix TS issues
interface IExtendedAxiosCacheAdapterOptions extends IAxiosCacheAdapterOptions {
store: { removeItem: (key: string) => void; }
uuid: string
}
// Create `axios-cache-adapter` instance, TTL 10 minutes
const cache = setupCache({
maxAge: 10 * 60 * 1000,
// Invalidate only when a specific option is passed through config
invalidate: async (config: IExtendedAxiosCacheAdapterOptions, request) => {
if (request.clearCacheEntry) {
await config.store.removeItem(config.uuid)
}
}
});
// Create `axios` instance passing the newly created `cache.adapter`
export const cachedAxios = axios.create({
adapter: cache.adapter,
});
I usually group all my api calls in a file api.ts
and export the functions:
import { AxiosResponse } from 'axios'
import { cachedAxios } from './axios'
const getDemoData = (baseUrl: string): Promise<IDemoData> => {
return cachedAxios.get(`${baseUrl}${API_URL}/demo-endpoint`)
.then((response: AxiosResponse<IDemoData>) => response.data)
.catch((error) => { throw error.message; });
}
export default { getDemoData }
Finally, the axios.spec.ts
test file for the api call:
import axios from 'axios'
import api from '../src/api'
// Mock jest and set the type
jest.mock('axios');
const mockedAxios = axios as jest.Mocked<typeof axios>;
jest.mock('../src/axios.ts', () => ({ cachedAxios: axios }));
describe('demo test api', () => {
afterAll(() => {
jest.restoreAllMocks()
});
it('should send a request to the API', async () => {
mockedAxios.get.mockResolvedValue({ data: { result: 'success' } });
const result = await api.getDemoData('demo argument');
expect(mockedAxios.get).toHaveBeenCalledWith(`${API_URL}/demo-endpoint`);
expect(result).toMatchObject({
result: 'success'
});
});
});