javascript - 如何使用 jest 和 enzyme 测试异步数据获取 react 组件?

原文 标签 javascript reactjs unit-testing jestjs enzyme

我有一个使用 useEffect 的 react 组件用于获取数据并相应地设置加载、成功和失败状态的钩子(Hook)。

import React, { useState, useEffect } from "react";
import { fetchData } from "./api";

function App({ id }) {
  const [data, setData] = useState(null);
  const [isFetching, setIsFetching] = useState(false);
  const [error, setError] = useState(null);
  useEffect(() => {
    setIsFetching(true);
    fetchData(id)
      .then(
        response => {
          setData(response.data);
          setIsFetching(false);
        },
        err => {
          setError(err);
          setIsFetching(false);
        }
      )
      .catch(err => {
        setError(err);
        setIsFetching(false);
      });
  }, [id]);

  if (data) {
    return <pre>{JSON.stringify(data)}</pre>;
  }
  if (isFetching) {
    return <div>fetching...</div>;
  }
  if (error) {
    return <pre>{JSON.stringify(error)}</pre>;
  }
  return <div>null</div>;
}

export default App;

我正在尝试使用 Jest 和 enzyme 来测试这个组件。

这是一个沙盒https://codesandbox.io/s/jest-enzyme-re41k

我收到一个奇怪的错误 Cannot read property 'isTTY' of undefined
有人可以帮助修复测试吗?

最佳答案

这是单元测试解决方案:
app.jsx :

import React, { useState, useEffect } from 'react';
import { fetchData } from './api';

function App({ id }) {
  const [data, setData] = useState(null);
  const [isFetching, setIsFetching] = useState(false);
  const [error, setError] = useState(null);
  useEffect(() => {
    setIsFetching(true);
    fetchData(id)
      .then(
        (response) => {
          setData(response.data);
          setIsFetching(false);
        },
        (err) => {
          setError(err);
          setIsFetching(false);
        },
      )
      .catch((err) => {
        setError(err);
        setIsFetching(false);
      });
  }, [id]);

  if (data) {
    return <pre>{JSON.stringify(data)}</pre>;
  }
  if (isFetching) {
    return <div>fetching...</div>;
  }
  if (error) {
    return <pre>{JSON.stringify(error)}</pre>;
  }
  return <div>null</div>;
}

export default App;
api.js :

export function fetchData() {
  // real implementation
}
app.test.jsx :

import App from './app';
import { mount } from 'enzyme';
import { fetchData } from './api';
import { act } from 'react-dom/test-utils';

jest.mock('./api.js', () => {
  return {
    fetchData: jest.fn(),
  };
});

describe('59586141', () => {
  afterEach(() => {
    jest.clearAllMocks();
  });
  it('should fetch data correctly', async () => {
    const mResponse = { data: { id: 1 } };
    const mProps = { id: 1 };
    fetchData.mockResolvedValueOnce(mResponse);
    const wrapper = mount(<App {...mProps}></App>);
    expect(wrapper.exists).toBeTruthy();
    expect(wrapper.find('div').text()).toBe('fetching...');
    await act(async () => {
      await new Promise((resolve) => setTimeout(resolve, 0));
    });
    wrapper.update();
    expect(wrapper.find('pre').text()).toBe(JSON.stringify(mResponse.data));
    expect(fetchData).toBeCalledWith(1);
  });

  it('should handle error if fetch data failure', async () => {
    const mError = new Error('some network error');
    const mProps = { id: 1 };
    fetchData.mockRejectedValueOnce(mError);
    const wrapper = mount(<App {...mProps}></App>);
    expect(wrapper.exists).toBeTruthy();
    expect(wrapper.find('div').text()).toBe('fetching...');
    await act(async () => {
      await new Promise((resolve) => setTimeout(resolve, 0));
    });
    wrapper.update();
    expect(wrapper.find('pre').text()).toBe(JSON.stringify(mError));
    expect(fetchData).toBeCalledWith(1);
  });
});

带有覆盖率报告的单元测试结果:

 PASS  src/stackoverflow/59586141/api.test.jsx (9.079s)
  59586141
    ✓ should fetch data correctly (119ms)
    ✓ should handle error if fetch data failure (12ms)

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |     93.1 |      100 |       80 |     91.3 |                   |
 app.jsx  |     93.1 |      100 |       80 |     91.3 |             22,23 |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        10.458s

源代码:https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/59586141

关于javascript - 如何使用 jest 和 enzyme 测试异步数据获取 react 组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59586141/

相关文章:

javascript - 如何将多个独特的 Facebook 跟踪像素(事件)放在一个页面上?

javascript - jQuery如何在单击按钮后在具有其他功能之前延迟并删除和添加类

reactjs - 带有 props.children 的 Typescript React 功能组件

scala - Play Framework -Dconfig.resource 不起作用

c# - 具有良好质量测试的开源项目

javascript - 制作 node.js 网络客户端

javascript - JavaScript中的内联函数和全局变量问题

javascript - 如何从handleSubmit中的react-query实现useMutation

javascript - Redux-saga:[…effects]已过时,不赞成所有人([…effects]),请更新您的代码

node.js - 单元测试 C++ v8 插件