簡體   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