首页 > 解决方案 > React 中的 Jest 模块模拟

问题描述

进入功能组件 + 钩子和 React 单元测试,我正在尝试执行以下操作:

在一个组件中,我使用实用程序 API 文件中的函数。在安装时,我对我的 api 进行异步函数调用。在该实用程序 API 文件中,我想以各种方式模拟该函数,因此当我在测试中渲染我的组件时,它会在挂钩中看到不同的响应。它将返回一个 Promise,它将根据我正在测试的内容解析为不同的值。

所以我不是在嘲笑第三方模块,而是在嘲笑我自己的模块。

/**
 * App.js
 */
import React, { useState, useEffect } from 'react'
import { getData } from './api'

export default function App() {
  const [data, setData] = useState()

  // get data from api on mount
  useEffect(() => {
    loadData()
  }, [])

  // get the data and set the "data" state variable
  const loadData = async () => {
    try {
      let d = await getData()  // <---- this is what i want to mock with different values per test
      setData(d)
    } catch (err) {
      setErr('Error occurred')
    }
  }

  render (
    <div>
      data is: {JSON.stringify(data)}
    </div>
  )
}

只是寻找一种方法来在每次测试的测试文件中定义模拟,所以当我的组件被渲染时,它将解析/拒绝不同的值

标签: reactjsmockingjestjsreact-hooks

解决方案


您可以从 api 模拟您的 getData 函数,如下所示:

import {render, wait} from 'react-testing-library';
import {getData} from 'path/to/api';

jest.mock('path/to/api', () => ({
    getData: jest.fn()
}))

it('succeeds when promise resolves', () => {
  // This overrides getData with a resolved promise
  getData.mockResolvedValue('foo');

  const { container } = render(<App />);
  // You need to wait for your mock promise to resolve
  return wait(() => {
    expect(container.textContent).toBe('data is: "foo"');
  });
});

it('fails when promise rejects', () => {
  // This overrides getData with a rejected promise
  getData.mockRejectedValue('oh no');

  const { container } = render(<App />);
  return wait(() => {
    expect(container.textContent).toBe('Error occurred');
  });
});

这基本上所做的是,当您的 api 被导入时,它会返回模拟工厂返回的字典。

您可以使用 模拟模块jest.mock,然后覆盖该函数以在每个测试中解析/拒绝不同的值。


推荐阅读