繁体   English   中英

已解决 - 在 Jest 和 Typescript 中使用自定义错误模拟 axios

[英]Solved - Mocking axios with custom error in Jest and Typescript

我想用自定义错误对象模拟 axios 发布请求。

获取令牌.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;

自定义错误对象是mockResponse 我想返回状态为 401 的响应。作为响应,数据对象应包含错误数组。

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",
    }
})

测试失败。

  Object {
    "error": true,
-   "message": "a",
+   "message": "Request failed with status code 400",
    "method": "GetToken",
    "module": "getToken.ts",
  }

当我检查 catch 语句中的代码时,此块运行

  else if (e instanceof Error){
        err.message=e.message
  }

如何返回我的自定义错误对象?

是的,我用 2 个不同的选项来解决。

感谢@jonrsharpe,axios 实例应该与 .test.ts 和 .ts 文件相同。

apiRoot.ts

import axios from "axios";
export const apiRoot = axios.create({
    headers: {
        "Access-Control-Allow-Origin": "*",
        "Content-Type": "application/json",
    }
})

获取令牌.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;

选项 1 :使用 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);
    })
})

选项 2模拟服务工作者

不要乱用 Axios

安装包

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);
    })
})

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM