javascript - 如何模拟 React Component 的功能并挂载组件?

标签 javascript reactjs jestjs

我有一个使用 fetch API 获取帖子的 React 组件。现在,在“开 Jest 测试”时,我想模拟获取 API 方法以从文件返回 json 数据。安装用于测试的组件,以通过查找类计数来计算帖子数。下面是代码。

测试文件代码

    import React from 'react';
    import { mount } from 'enzyme';
    import dummyjson from '../dummydata.json';
    import DemoApp from '../index';

    describe('xxxx test component', () => {
  it('first test', async () => {
    global.fetch = jest.fn(() => Promise.resolve(dummyjson));
    const wrapper = shallow(<DemoApp />, { disableLifecycleMethods: true });
    expect(wrapper.state('isLoaded')).toBe(false);
    await wrapper.instance().loadPosts();
    expect(wrapper.state('isLoaded')).toBe(true);
  });
    });

React 组件代码

        import React from 'react';
    /* eslint class-methods-use-this: ['error', { 'exceptMethods': ['fetch'] }] */

    export default class DemoApp extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          error: null,
          isLoaded: false,
          items: [],
        };
      }

   componentDidMount() {
    this.loadPosts().then(
      (result) => {
        this.setState({
          isLoaded: true,
          items: result,
        });
      },
      (error) => {
        this.setState({
          isLoaded: true,
          error,
        });
      },
    );
  }

  loadPosts() {
    return fetch('https://jsonplaceholder.typicode.com/posts')
      .then(res => res.json()).then(result => result)
      .catch(error => error);
  }

      render() {
        const { error, isLoaded, items } = this.state;
        if (error) {
          return <div>Error: {error.message}</div>;
        } else if (!isLoaded) {
          return <div>Loading...</div>;
        }
        return (
          <div>
            {items.map(item => <div className="somecssclass"> {item.title} {item.title}</div>)}
          </div>
        );
      }
    }

下面是dummydata json

    [
    {
      "userId": 1,
      "id": 1,
      "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
      "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
    },
    {
      "userId": 1,
      "id": 2,
      "title": "qui est esse",
      "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
    }
]

即使我在 React 组件类文件中为 fetch 方法提供了以下异常,但我仍收到低于错误/警告的错误。 /* eslint class-methods-use-this: ['error', { 'exceptMethods': ['fetch'] }] */

enter image description here

我们如何解决这个警告/错误?

非常感谢任何帮助。 谢谢。

最佳答案

存在竞争条件。 loadPosts 是异步的,而 test 是同步的,没有 promise to chain 等待 fetch promise chain 完成。

控制流和测试方法存在问题。 loadPosts 需要返回一个 promise,所以它可以被链接起来:

  loadPosts() {
    return fetch('https://jsonplaceholder.typicode.com/posts')...;
  }

对其进行单元测试的一种正确方法是在一次测试中测试 loadPosts 并直接对其进行测试:

  it('...', async () => {
    global.fetch = jest.fn(() => Promise.resolve(dummyjson));
    const wrapper = shallow(<DemoApp />, { disableLifecycleMethods: true });
    expect(wrapper.state('isLoaded').toBe(false);
    await wrapper.instance().loadPosts();
    expect(wrapper.state('isLoaded').toBe(true);
  });

在另一个测试中,loadPosts 可以被 stub /模拟并断言它在 componentDidMount 中被调用。

另请注意,global.fetch = 一劳永逸地替换了它。最好用 jest.stub 模拟它。

关于javascript - 如何模拟 React Component 的功能并挂载组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52691292/

相关文章:

javascript - 为什么我不能使用 setState 将对象传递给状态?

javascript - 如何让jest不区分负零和正零?

reactjs - 使用 react 测试库测试到达路由器的导航

javascript - JS悬停元素之间的负空间

javascript - React onFocus 和 onFocusCapture 的区别

reactjs - 如何让 React Router v6 响应 404 状态码

javascript - 如何在 JavaScript 函数中将文本转换为 HTML 并使用 jest 进行单元测试

javascript 验证通过获取元素 id 来检查输入是否为空

javascript - 使用 Javascript 的正则表达式

javascript - Mozilla 关闭示例