【问题标题】:Why does mocked axios get method return undefined?为什么模拟 axios get 方法返回未定义?
【发布时间】:2019-09-06 05:55:19
【问题描述】:

我编写了一个相当简单的异步方法,通过 HTTP 检索结果:

import axios from "axios";

const BASE_URI = "http://api.tvmaze.com";

export const getSearchShows = async (search: string) => {
  const uri = `${BASE_URI}/search/shows?q=${encodeURIComponent(search)}`;
  const response = await axios.get(uri);

  return response.data;
};

我想对它进行单元测试。所以我写了下面的 Jest 测试,它打算模拟 axios 并返回假结果,然后我可以断言:

import axios from "axios";

import fakeSearchShowsResponse from "../data/search-shows--q=test.json";

import { getSearchShows } from "./TvShows.http";

jest.mock("axios");

describe("TvShows.http", () => {
  describe("getSearchShows", () => {
    it("retrieves shows over http and correctly deserializes them", async () => {

      const mockAxiosGet = jest.spyOn(axios, "get");

      mockAxiosGet.mockImplementation(async () => fakeSearchShowsResponse);

      const shows = await getSearchShows("test");

      console.log(mockAxiosGet.mock.calls);

      expect(shows[0].id).toEqual(139);

    });
  });
});

我预计,由于调用 jest.mock("axios"),axios get 方法将被替换为模拟的 Jest 方法。

此外,我预计由于调用 mockAxiosGet.mockImplementation 并将其传递给函数,对 axios get 方法的调用实际上会调用我的模拟函数,从而允许我将测试数据替换为真实数据。

实际发生的是对 axios get 的调用返回 undefined,导致我的测试断言失败。

然而,奇怪的是,Jest 间谍仍然记录该方法被调用——console.log 输出一个调用。

那么,当我明确提供返回值的模拟实现时,为什么这个所谓的模拟方法会返回 undefined?

还是我误解了 mockImplementation 的使用方式?

【问题讨论】:

    标签: javascript reactjs unit-testing jestjs axios


    【解决方案1】:

    所以经过一些实验,jest.mock("axios") 调用似乎干扰了jest.spyOn(axios, "get"); 调用。

    删除 jest.mock 调用后,它现在从 jest.spyOn 调用返回我的模拟值。

    我认为这可能是因为 jest.mock 调用被提升了,而 jest.spyOn 调用没有。因此,被测模块脱离了悬挂的模拟,而不是未悬挂的模拟。

    【讨论】:

      【解决方案2】:

      jest.mock('axios') 将模拟整个模块,用存根替换所有内容。所以它不一定与jest.mock() 被提升的事实有关,它只是为了确保在导入之前模拟依赖关系。这只是返回 undefined 的存根。

      同时,你可以

      import axios from 'axios';
      
      jest.mock('axios');
      
      console.log(axios); // mocked
      
      describe('suite', () => {
        it('test', () => {
          axios.get.mockResolvedValue('{"test": "test"}');
          // --------------------------^
          // you class would get this when calling axios.get()
      
          // you could also do some assertion with the mock function
          expect(axios.get).toHaveBeenCalledTimes(1);
          expect(axios.get).toHaveBeenCallWith('http://some-url');
        });
      });
      

      【讨论】:

        猜你喜欢
        • 2020-10-24
        • 1970-01-01
        • 2021-12-10
        • 2010-12-19
        • 2022-10-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-29
        相关资源
        最近更新 更多