如何使用jest和酶测试API调用?

时间:2018-04-17 22:05:30

标签: reactjs api tdd jestjs enzyme

我有一个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;

3 个答案:

答案 0 :(得分:5)

这对单元测试来说是一件好事,它们迫使你编写更好的代码。因此,要正确测试此组件,您应该执行以下操作:

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

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

  4. 请注意,使用此代码组织,您可以单独测试API调用和SearchContainer,而无需调用API服务。

答案 1 :(得分:2)

我会通过将<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"> <div class="text-primary">Hello World!</div>解压缩到包含performSearch的模块来解决此问题。有关测试您不拥有的内容,请参阅this great article

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

例如:

jest.fn()

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

答案 2 :(得分:0)

许多其他答案建议使用 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