用玩笑测试 axios 拦截器

Testing axios interceptors with jest

我正在使用 axios 拦截器将授权令牌添加到其 header。拦截器工作正常。

//api.js
import { getAccessToken } from "./utils";

const apiInstance = axios.create();

apiInstance.interceptors.request.use((configIns) => {

  const token = getAccessToken();
  configIns.headers.Authorization = token ? `Bearer ${token}` : "";
  return configIns;

});

export { apiInstance };

这是我用来测试拦截器的测试文件。

// api.test.js

import { apiInstance } from "./api"
import {getAccessToken} from "./utils";

describe("request interceptor", () => {
    it("API request should add authorization token to header", () => {

      const getAccessToken = jest.fn(getAccessToken);
      getAccessTokenMock.mockReturnValue("token");

      const result = apiInstance.interceptors.request.handlers[0].fulfilled({ headers: {} });

      expect(getAccessTokenMock.mock.calls.length).toBe(1);
      expect(result.headers).toHaveProperty("Authorization");
    });
  });

但是 getAccessToken 函数在拦截器中由于某种原因没有被模拟。 测试失败。

Jest 中的模拟不是这样工作的。通过调用(我假设变量应该是 getAccessTokenMock,而不是 getAccessToken):

const getAccessTokenMock = jest.fn(getAccessToken);
getAccessTokenMock.mockReturnValue("token");

你所做的是:你创建新的本地模拟,当被调用时,会调用你的 getAccessToken 函数。然后你模拟 return 值。但是,您的 getAccessTokenMock 永远不会被调用,因为它与您的实现中的实例不同!

您需要做的是从 ./utils 文件中模拟您的实际函数 getAccessToken。可以这样做,例如,像这样:

import { apiInstance } from "./api"
import {getAccessToken} from "./utils";

// Mock here:
jest.mock('./utils', () => ({
  getAccessToken: jest.fn(() => 'token')
});

describe("request interceptor", () => {
  it("API request should add authorization token to header", () => {
    const result = apiInstance.interceptors.request.handlers[0].fulfilled({ headers: {} });

    expect(getAccessToken.mock.calls.length).toBe(1);
    expect(result.headers).toHaveProperty("Authorization");
  });
});

这里发生的事情是,当文件被加载时,jest.mock 将首先 运行 并将您对 getAccessToken 的实现替换为模拟 - 然后可以从两者访问它实现和测试(作为同一个实例),意味着你可以验证它是否被调用。

请找到更多关于 mocks here or here. Alternatively you can also use spyOn 的信息以获得类似的结果(那么你不需要 jest.mock,但你必须导入你的 getAccessToken 函数而不解构)。