【问题标题】:How do I mock constructor state initialisation with Jest如何使用 Jest 模拟构造函数状态初始化
【发布时间】:2019-08-06 20:28:50
【问题描述】:

node.js 的新手。我正在编写一个包装底层axios 库的JS API 客户端。在单元测试中,我使用 Jest 模拟 axios。

在我的 API 类的构造函数中,我传入一个 URL,并使用 axios.create 函数创建一个自定义的 axios 实例并将其绑定到客户端属性。

当我使用 jest.mock('axios') 模拟 axios 依赖项时出现问题 - 尝试调用 axios.get 时在测试中引发 TypeError:

TypeError: Cannot read property `get` of undefined

我明白为什么会发生这种情况,但我还没有找到一种方法来模拟 axios 并且不让客户字段未定义。除了通过构造函数注入 axios 之外,有没有办法解决这个问题?

客户端代码和测试如下:


client.js

jest.mock("axios");
const axios = require("axios");
const mockdata = require("./mockdata");
const ApiClient = require("../../../src/clients/apiclient");


const BASE_URL = "https://www.mock.url.com"

const mockAxiosGetWith = mockResponse => {
  axios.get.mockResolvedValue(mockResponse);
};

test("should make one get request",  async () => {
  mockAxiosGetWith(MOCK_RESPONSE)

  // the client field in apiclient is undefined
  // due to the jest module mocking of axios
  const apiclient = new ApiClient.AsyncClient(BASE_URL);


  // TypeError: Cannot read property `get` of undefined
  return await apiclient.get("something").then(response => {
    expect(axios.get).toHaveBeenCalledTimes(1);
  });

});

client.test.js

const axios = require("axios");

const getClient = (baseUrl = null) => {
  const options = {
    baseURL: baseUrl
  };

  const client = axios.create(options);

  return client;
};

module.exports = {
  AsyncClient: class ApiClient {
    constructor(baseUrl = null) {
      this.client = getClient(baseUrl);
    }

    get(url, conf = {}) {
      return this.client
        .get(url, conf)
        .then(response => Promise.resolve(response))
        .catch(error => Promise.reject(error));
    }

  }
};

【问题讨论】:

  • 你不要模拟 axios 的实现。应该有jest.mock("axios", () => ({ get: jest.fn }))。我不能说这是否是这里唯一的问题。
  • @estuthanks 回复。 jest 允许使用 jest.fn 自动模拟每个导出的函数的模块模拟​​ - 这不是这里的问题。
  • 但是axios 只导出一个拥有create 函数的对象。这与直接导出 create 的模块不同。所以@estusis 对他关于如何模拟axios 的建议是正确的。即使是真正的嘲笑也应该看起来不同。我会提供答案。

标签: javascript node.js unit-testing jestjs axios


【解决方案1】:

您需要模拟axios,因此它将返回一个包含create 函数的对象,该函数应该返回带有get 的对象

import axios from 'axios'
jest.mock('axios', () => ({create: jest.fn()}))


test("should make one get request",  async () => {
  const get = jest.fn(()=>Promise.resolve(MOCK_RESPONSE))
  axios.create.mockImplementation(()=>({get}))

  const apiclient = new ApiClient.AsyncClient(BASE_URL);

  await apiclient.get("something")
  expect(get).toHaveBeenCalledTimes(1);

});

【讨论】:

  • 感谢 Andreas Koberle - 这很有效,现在我更了解 Jest 的嘲弄,感谢您和 @estus。对您和 estus 的评论都投了赞成票,并将此答案标记为正确。干杯!
猜你喜欢
  • 2011-05-21
  • 2020-01-08
  • 2019-01-01
  • 2017-08-17
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 2022-12-14
  • 1970-01-01
相关资源
最近更新 更多