I want to mocking axios post request with custom error object.
getToken.ts
const GetToken = async (params:ITokenParams):Promise<ITokenResult | IError>=>{
try{
const api = axios.create({
headers: {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json",
},
});
const {data} = await api.post<ITokenResult>("https://someURL", { ...params });
return data;
}
catch(e){
let err:IError={
error:true,
module:path.basename(__filename),
method:GetToken.name
};
if(e instanceof AxiosError && e.response?.data?.errors){
let errorsArray:IApiError[]=e.response?.data?.errors;
err.message=errorsArray.length>0?errorsArray[0].detail : e.message;
}
else if (e instanceof Error){
err.message=e.message
}
return err;
}
}
export default GetToken;
The custom error object is mockResponse. I want to return a response with status 401. In response, data object should includes errors array.
getToken.test.ts
import {axiosInstance} from '../../utils/axios-instance';
import GetToken from '@App/api/oauth/getToken';
jest.mock('../../utils/axios-instance.ts');
describe('Token from OAuth', () => {
test('Return error for expired code', async () => {
const mockResponse = {
data:{},
status: 401,
statusText:"Unauthorized",
headers: {},
config: {} ,
response:{
data: { errors: [{ detail: 'a' }] }
}
};
const response = {
error: true,
module: 'getToken.ts',
method: 'GetToken',
message: 'a'
};
const mockedAxiosInstance = axiosInstance as jest.MockedFunction<typeof axiosInstance>;
(mockedAxiosInstance.post as jest.Mock).mockRejectedValueOnce(mockResponse);
const result= await GetToken({
client_id:process.env.APPLICATION_ID,
client_secret:process.env.APPLICATION_SECRET,
code:"some-codes",
grant_type:"authorization_code"
});
expect(result).toEqual(response);
})
})
axios-instance.ts
import axios from "axios";
export const axiosInstance = axios.create({
headers: {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json",
}
})
The test is fail.
Object {
"error": true,
- "message": "a",
"message": "Request failed with status code 400",
"method": "GetToken",
"module": "getToken.ts",
}
When i check the code in the catch statement this block runs
else if (e instanceof Error){
err.message=e.message
}
How can i return my custom error object?
CodePudding user response:
Yes I solve with 2 different option.
Thanks to @jonrsharpe, axios instance should be same both .test.ts and .ts files.
apiRoot.ts
import axios from "axios";
export const apiRoot = axios.create({
headers: {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json",
}
})
getToken.ts
...
import {apiRoot} from '@App/utils/apiRoot';
const GetToken = async (params:ITokenParams):Promise<ITokenResult | IError>=>{
try{
// This line change with apiRoot. We don't use axios.create.
const {data} = await apiRoot.post<ITokenResult>("someURL", { ...params });
return data;
}
catch(e){
...
}
}
export default GetToken;
Option-1 : Test with axios
getToken.test.ts
import {apiRoot} from '@App/utils/apiRoot';
import GetToken from '@App/square-api/oauth/getToken';
import {AxiosError} from 'axios';
//mock the instance from apiRoot
jest.mock('@App/utils/apiRoot.ts');
describe('Token from OAuth', () => {
test('Return error for expired code', async () => {
// Expected response from GetToken method
const response = {
error: true,
module: 'getToken.ts',
method: 'GetToken',
message: 'a'
};
const mockedAxiosInstance = apiRoot as jest.MockedFunction<typeof apiRoot>;
(mockedAxiosInstance.post as jest.Mock).mockRejectedValueOnce(new AxiosError("Unauthorized","401",{},{},
{
data: { errors: [{ detail: 'a' }] },
status:401,
statusText:'Unauthorized',
headers:{},
config:{}
}));
const result= await GetToken({
client_id:process.env.APPLICATION_ID,
client_secret:process.env.APPLICATION_SECRET,
code:"some-code",
grant_type:"authorization_code"
});
expect(result).toEqual(response);
})
})
Option-2 : Mock Service Worker
Don't mess with Axios
install packages
npm install msw --save-dev
getToken.test.ts
import { rest } from 'msw'
import { setupServer } from 'msw/node'
import GetToken from '@App/square-api/oauth/getToken';
const mockResponse = { errors: [{ detail: 'a' }] } ;
const response = {
error: true,
module: 'getToken.ts',
method: 'GetToken',
message: 'a'
};
const server = setupServer(
// Url should be same with post request in getToken.ts
rest.post("someURL", (req, res, ctx) => {
return res(
ctx.set('Content-Type', 'application/json'),
ctx.status(401),
ctx.json({...mockResponse})
)
})
)
beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())
describe('Token from OAuth', () => {
test('Return error for expired code', async () => {
const result= await GetToken({
client_id:process.env.APPLICATION_ID,
client_secret:process.env.APPLICATION_SECRET,
code:"some-code",
grant_type:"authorization_code"
});
expect(result).toEqual(response);
})
})