I have an api service where I have different methods to make calls to the APIs. I've successfully tested all of the GET requests but I am having troubles testing the POST requests.
This is the method:
export default class ApiService {
static makeApiCall = <T>(
url: string,
oneCb: <T>(d: Data) => T,
secondCb: (d: T) => void,
errorCb?: (a: ErrorModel) => void,
method = 'get',
data = {},
): Promise<void> => {
const config: AxiosRequestConfig = {};
if (method === 'post') {
config.headers = header;
return ApiClient.post(url, data, config)
.then(res => callback(normalizeCallback(res.data))).catch(error => someHandler(error));
} else {
return ApiClient.get(url)
.then(res => callback(normalizeCallback(res.data))).catch(error => someHandler(error));
}
};
// ONLY ONE POST METHOD TO MAKE IT MORE CLEAR
static someArchiveMethod = (
callback: (a: SuccessModel) => void,
errorCallback: (error: ErrorModel) => void,
cardId: string
): Promise<void> => {
return ApiService.makeApiCall<SuccessfulResponse>(
'appreciationCard/archive',
Normalizer.successfulResponse,
callback,
errorCallback,
'post',
{ cardId }
);
};
// HERE BELOW THE GET METHODS
static getPeople = (cb: (a: PeopleModel[]) => void, page?: number, limit?: number): Promise<void> => {
const queryDetails = { page, limit };
return ApiService.makeApiCall<PeopleModel[]>(
`people?${toQueryString(queryDetails)}`,
Normalizer.normalizePeople,
callback
);
};
};
This is how I am testing everything related to the GETs:
describe('apiService', () => {
beforeAll(() => {
expect(ApiClient.defaults.headers.common.Authorization).toBe('Bearer test token');
// @ts-ignore
ApiClient.get.mockImplementation((url: string) => {
return Promise.resolve({ data: mockData });
});
});
it('should call api client method', () => {
ApiService.makeApiCall(
'testUrl',
data => data,
res => res,
err => err,
'get'
);
expect(ApiClient.get).toBeCalledTimes(1);
expect(ApiClient.get).toBeCalledWith('testUrl');
});
it('should call callbacks consequently', done => {
ApiService.makeApiCall('testUrl', firstCallback, secondCallback).then(() => {
expect(firstCallback).toBeCalledTimes(1);
expect(firstCallback).toBeCalledWith(mockData);
expect(secondCallback).toBeCalledTimes(1);
expect(secondCallback).toBeCalledWith(firstCallback(mockData));
done();
});
});
});
describe('api service error flow', () => {
beforeAll(() => {
// @ts-ignore
ApiClient.get.mockImplementation((url: string) => {
console.log('error result');
return Promise.reject(mockError);
});
});
it('should handle error', done => {
console.error = jest.fn();
const firstCallback = jest.fn((data: any) => data);
const secondCallback = jest.fn((data: any) => data);
ApiService.makeApiCall('testUrl', firstCallback, secondCallback).then(() => {
expect(firstCallback).toBeCalledTimes(0);
expect(secondCallback).toBeCalledTimes(0);
expect(console.error).toBeCalledTimes(1);
expect(console.error).toBeCalledWith('ApiClient testUrl', mockError);
done();
});
});
});
describe('apiService methods', () => {
beforeAll(() => {
ApiClient.get.mockImplementation((url: string) => {
expect(ApiClient.defaults.headers.common.Authorization).toBe('Bearer test token');
return Promise.resolve({ data: mockData });
});
});
it('getPeople method call with one param', () => {
ApiService.getPeople(jest.fn(), 1, 1).then(() => {
expect(ApiClient.get).toBeCalledWith('people?page=1&limit=1');
});
});
})
I thought that only by changing all of the instances of ApiClient.get
to ApiClient.post
it will work to test the POST requests. But when I attempt to do that it says that can not read mockImplementation of undefined
. I tried changing the methods in the tests to use the post
param in order to overwrite the param method = 'get'
but I don't have any success, I get this error
TypeError: apiClient_1.default.post is not a function
Any thoughts?
import service from './Service'; jest.mock ('./Service', () => jest.fn ()); service.yourFunction = jest.fn ( () => { /*your mock*/ }) Say your service.js is in javascript/utils, create a javascript/utils/_ mocks _ and inside it create a service.js file, you can then mock the entire class in this file, eg:
Jest encountered an unexpected token This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript. By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".
By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules". Here's what you can do: • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config. • If you need a custom transformation specify a "transform" option in your config.
• If you need a custom transformation specify a "transform" option in your config. • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
I've investigated your problem. First of all, I want to tell that your code has a couple of issues like calling callback that you didn't define, unclear defining of ApiClient
etc.
So, I created a Repl example to reproduce your issue in which I simplified your code a bit but all the main elements are there.
Please, take a look https://repl.it/@SergeyMell/Some-Jesting
It works successfully for both get
and post
methods with no issues.
Here, are the main points you should pay your attention on:
axios
as ApiClient
. (It was not clear from your question so I assumed that it is so)
const ApiClient = require('axios');
axios
(Suppose, you do the same)
jest.mock('axios');
Putting mocks to both get
and post
requests in a similar manner (same to your way)
ApiClient.get.mockImplementation((url) => {
return Promise.resolve({ data: mockData });
});
ApiClient.post.mockImplementation((url) => {
return Promise.resolve({ data: mockData });
});
So, please, check my example, check the differences with your code and let me know regarding some additional detalization that you may need.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With