如何模拟AxiosInstance?

s1n*_*7ax 3 typescript jestjs axios ts-jest

我有axios以下HttpClient课程

export default class HttpClient {
  constructor(baseUrl: string) {
    const axiosInstance = axios.create({
      validateStatus(status: number) {
        return status === 200 || status === 201;
      },
    });

    axiosInstance.interceptors.request.use((config) => {
      if (AuthUtil.getAuthHeader()) config.headers = AuthUtil.getAuthHeader();
      return config;
    });

    return new Proxy(this, {
      get(_, prop) {
        return (url: string, ...args: any) => {
          url = baseUrl + url;
          return Reflect.get(axiosInstance, prop)(url, ...args);
        };
      },
    });
  }

  get<T = any, R = AxiosResponse<T>>(_url: string, _config?: AxiosRequestConfig): Promise<R> {
    return Promise.resolve(null);
  }
.....
}
Run Code Online (Sandbox Code Playgroud)

这是使用的服务HttpClient

export default class UserManagementServiceImpl implements UserManagementService {
  private client = new HttpClient('/api/user');

  async getUser(): Promise<User> {
    const res = await this.client.get('/user');
    return res.data;
  }
Run Code Online (Sandbox Code Playgroud)

我正在测试该服务如下。在这里我不是userService.getUser直接调用,而是为了测试我创建了这个。

describe('User actions', () => {
  test('creates GET_TERMS_SUCCESS', async () => {
    jest.mock('axios', () => {
      return {
        create: jest.fn().mockReturnValue({
          interceptors: {
            request: { use: jest.fn(), eject: jest.fn() },
            response: { use: jest.fn(), eject: jest.fn() },
          },

          get: jest.fn().mockReturnValue({ data: user }),
        }),
      };
    });

    const user = await userService.getUser();
  });
});

// ERROR:
/*
Error: Error: connect ECONNREFUSED 127.0.0.1:80
*/
Run Code Online (Sandbox Code Playgroud)

我已经尝试了堆栈溢出中列出的多种其他解决方案,但似乎不起作用。这应该怎么做呢?

s1n*_*7ax 8

更新 [2022 年 5 月 18 日]

我想我终于弄清楚了如何结合axios-mock-adapterAxiosInstanceaxios.create().

我们在测试中所做的是将实例分配为本地可访问的AxiosStatic返回值。axios.create于是我们axios像往常一样嘲笑using axios-mock-adapter

import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import UserManagementServiceImpl from '../../../services/impl/UserManagementServiceImpl';

jest.mock('axios', () => {
  return {
    ...(jest.requireActual('axios') as object),
    create: jest.fn().mockReturnValue(jest.requireActual('axios')),
  };
});

const mockAdapter = new MockAdapter(axios);

test('hello', async () => {
  const userService = new UserManagementServiceImpl();

  mockAdapter.onGet('/api/user/user').reply(200, { name: 'name' });
  const r = (await userService.getUser()) as any;
  expect(r.name).toBe('name');
});
Run Code Online (Sandbox Code Playgroud)

旧答案

jest.mock() 显然应该始终位于测试生命周期方法之外。

jest.mock('axios', () => {
  return {
    create: jest.fn().mockReturnValue({
      interceptors: {
        request: { use: jest.fn(), eject: jest.fn() },
        response: { use: jest.fn(), eject: jest.fn() },
      },

      get: jest.fn().mockReturnValue({ data: user }),
    }),
  };
});

describe('User actions', () => {
  test('test', async () => {
    const user = await userService.getUser();
  });
});
Run Code Online (Sandbox Code Playgroud)

您也可以稍后模拟和定义函数

jest.mock('axios')

describe('User actions', () => {
  test('test', async () => {
    (axios.create as jest.Mock<any, any>).mockReturnValue({
      interceptors: {
        request: { use: jest.fn(), eject: jest.fn() },
        response: { use: jest.fn(), eject: jest.fn() },
      },

      get: jest.fn().mockReturnValue({ data: { name: 'name' } }),
    });

    const user = await userService.getUser();
  });
});
Run Code Online (Sandbox Code Playgroud)