【问题标题】:How to test API calls in react using jest and enzyme?如何使用 jest 和酶测试 API 调用?
【发布时间】:2018-09-28 00:21:45
【问题描述】:

我有一个 React 容器,我正在其中进行 API 调用,并希望能够使用 jest 和酶来测试它,但不确定如何去做。

这是我的代码:

import React from "react";
import Search from "../../components/Search";
import { API_KEY } from "../../../config";

class SearchContainer extends React.Component {
  state = {
    articles: []
  };

  performSearch = event => {
    fetch(
      `http://content.guardianapis.com/search?q=${event}&api-key=${API_KEY}`
    )
      .then(response => response.json())
      .then(data => this.setState({ articles: data.response.results }));
  };

  render() {
    return (
      <Search
        performSearch={this.performSearch}
        articles={this.state.articles}
      />
    );
  }
}

export default SearchContainer;

【问题讨论】:

    标签: reactjs api tdd jestjs enzyme


    【解决方案1】:

    单元测试的好处在于,它们迫使您编写更好的代码。因此,要正确测试此组件,您应该执行以下操作:

    1. 从组件中提取 performSearch 到一个单独的文件中,例如api.js
    2. 在您的 api.js 文件中模拟 performSearch (jest: mock a module)

    3. 现在您可以测试是否调用了 fetch 函数。

    请注意,使用此代码组织,您可以在不调用 API 服务的情况下单独测试 API 调用和 SearchContainer。

    【讨论】:

    • 您好,感谢您的回复。我已经按照你说的做了。你能告诉我如何为此编写测试吗?
    【解决方案2】:

    我会通过将performSearch 提取到一个包装fetch 的模块中来解决这个问题。请参阅 this great article 测试不属于您的东西。

    之后,如果您将文章状态存储在搜索组件中,您可能不再需要SearchContainer。由于您已经在使用 performSearch 属性的依赖注入,您可以传入一个模拟对象来代替它并使用 jest.fn() 来确保它被调用。

    例如:

    const fakePerformSearch = jest.fn();
    const component = Shallow(<Search performSearch={fakePerformSearch}/>);
    expect(fakePerformSearch).toHaveBeenCalled();
    

    然后像测试任何 JavaScript 一样测试新的 fetch 包装器。

    【讨论】:

    • 您好,感谢您的回答!我去提取了API,您能检查一下是否可以吗? import { API_KEY } from "../../config"; const fetchArticles = event =&gt; { return fetch( `http://content.guardianapis.com/search?q=${event}&amp;api-key=${API_KEY}` ).then(response =&gt; response.json()); }; export default fetchArticles;
    【解决方案3】:

    许多其他答案建议使用 Jest 的导入模拟器或模拟函数,但是,这会测试实现而不是行为。

    最好是存根环境而不是工具。让我们使用像 nock 这样的 HTTP 拦截器编写一个测试。这样做的好处是您可以迁移到不同的数据获取工具或更改获取行为并从您的测试中获得反馈。

    // src/SearchContainer/SearchContainer.test.js
    import React from "react";
    import nock from "nock";
    import {mount} from "enzyme";
    
    import Search from "../../components/Search";
    import { API_KEY } from "../../../config";
    
    describe('<SearchContainer />', async () => {
      it('searches for articles', () => {
        const scope = nock('http://content.guardianapis.com')
          .get('/search')
          .query({'api-keys': API_KEY, {q: 'some article'}})
          .reply(200, {
            results: [...]
          })
        const wrapper = mount(<SearchContainer />);
        const searchInput = wrapper.find('[data-test-id="search-input"]');
        await searchInput.simulate('change', { target: { value: 'some article' } });
        const articles = wrapper.find('[data-test-id="articles"]');
        expect(articles.length > 0).toBe(true);
        expect(scope.isDone()).toBe(true);
      });
    });
    

    为了更深入地了解测试 API 调用,我写了一篇博文 Testing Components that make API calls

    【讨论】:

      猜你喜欢
      • 2019-04-21
      • 1970-01-01
      • 2019-11-15
      • 2019-04-24
      • 2020-08-22
      • 2018-03-25
      • 2020-06-28
      • 1970-01-01
      • 2019-04-24
      相关资源
      最近更新 更多