如何模拟由 mobx 商店导入的辅助函数发出的异步 axios 请求

问题描述

我正在尝试为我的 mobX 存储中的一个方法编写测试,该方法调用一个辅助方法 getPages,该方法进行异步 API 调用获取一些数据。在为 getPages 辅助函数编写测试时,我成功地模拟了 axios,但现在我正在测试 mobx 商店,我似乎无法再模拟 axios。

是不是因为store文件没有直接导入axios?

我是否必须模拟 getPages 辅助函数?如果是这样,我该怎么做?

目前 API 调用 await axios.get('${process.env.REACT_APP_BACKEND_URL}/pages'); 返回的是 undefined 而不是模拟值。最终我只需要这个调用来返回模拟值。

谢谢

MobX 商店

import { makeAutoObservable } from 'mobx';
import { getPages } from 'lib/api';

class DocumentStore {
  pages = [];
  currentPage = null;

  constructor() {
    makeAutoObservable(this);
  }

  setPages = (pages) => {
    this.pages = pages;
    return this.pages;
  };

  setCurrentPage = (page) => {
    this.currentPage = page;
    return this.currentPage;
  };

  getPages = async (documentName) => {
    const pageUrls = await getPages('a-test',documentName);
    this.setCurrentPage(pageUrls[0]);
    this.setPages(pageUrls);
  };
}

export default DocumentStore;

API 调用

export const getPages = async () => {
  let resp;
  try {
    resp = await axios.get(
      `${process.env.REACT_APP_BACKEND_URL}/pages`,);
  } catch (err) {
    throw new Error(err);
  }

  if (resp?.data?.urls) {
    return resp.data.urls;
  } else {
    throw new Error('Unable to fetch Urls');
  }
};

测试文件

import DocumentStore from './index';
import axios from 'axios';

const TEST_PAGES = [
  {
    url: 'URL1',},{
    url: 'URL2',{
    url: 'URL3',];

const FETCH_PAGES_MOCK = {
  data: {
    urls: TEST_PAGES,};

jest.mock('axios');

describe('DocumentStore',() => {
  describe('getPages',() => {
    axios.get.mockResolvedValue(FETCH_PAGES_MOCK);
    it('fetches pages',() => {
      const store = new DocumentStore();
      expect(store.pages.length).toEqual(0);
      store.getPages();
      expect(store.pages.length).toEqual(3);
    });
  });
});

解决方法

模拟间接依赖(axios.get())和模拟直接依赖(getPages 模块中的lib/api),它们都可以。取决于您希望将哪些模块作为一个单元。我更喜欢较小的单元,只模拟测试代码直接依赖的模块。

过大的单元会使测试更加复杂,难以定位问题。庞大的单元接近更高级别的测试,例如集成测试、e2e 测试。

对于您的情况,您在调用 await 方法时忘记使用 store.getPages()

例如

index.test.js

jest.mock('axios');

describe('DocumentStore',() => {
  describe('getPages',() => {
    axios.get.mockResolvedValue(FETCH_PAGES_MOCK);
    it('fetches pages',async () => {
      const store = new DocumentStore();
      expect(store.pages.length).toEqual(0);
      await store.getPages('test');
      expect(store.pages.length).toEqual(3);
      expect(axios.get).toBeCalled();
    });
  });
});