如何为React无状态功能组件模拟API?

时间:2019-10-29 21:07:51

标签: reactjs mocking jestjs fetch

我正在尝试测试一个在useEffect生命周期挂钩期间进行Fetch调用的无状态功能React组件。我想制作一个模拟api文件,该文件将在运行Jest单元测试时拦截此调用,但是我没有运气尝试实现这一目标。

我的组件:App.js

import React, { useState, useEffect } from 'react';
import Form from './Form';
import Image from './Image';
import unsplash from '../services/unsplash';

function App() {
  const [deStat, setDeStat] = useState({
    term: '',
    images: [],
    status: 'initial'
  });

  const fetchImages = async term => {
    setDeStat({
      status: 'searching',
      term: term,
      images: []
    });

    try {
      const images = await unsplash(term);
      setDeStat({
        status: 'done',
        images
      });
    } catch (error) {
      setDeStat({
        status: 'error'
      });
    }
  };

  useEffect(() => {
    fetchImages('Mountains');
  }, []);

  return (
    <div className="App">
      <Form fetchImages={fetchImages} />

      {deStat.status === 'searching' && <h3>Searching for {deStat.term}</h3>}
      {deStat.status === 'done' && deStat.images.length === 0 && (
        <h3>
          Sorry sucker, no results{' '}
          <span role="img" aria-label="sad">
            ?
          </span>
        </h3>
      )}
      {deStat.status === 'error' && <h3>Oops... error!</h3>}

      <div className="images-container">
        <h5>Images okay!</h5>
        {deStat.images.map(image => (
          <Image image={image} key={image.id} />
        ))}
      </div>
    </div>
  );
}

export default App;

我的模拟服务(services/__mocks__/unsplash.js):

const fakeData = [
  {
    id: 1,
    categories: [{ title: "Nice image" }],
    user: {
      name: "Mr. Photographer"
    },
    links: {
      html: "https://www.leighhalliday.com"
    },
    urls: {
      small: "https://www.image.com/nice.jpg"
    },
    likes: 10
  }
];

export default async term => {
  return await new Promise(resolve => {
    resolve(fakeData);
  });
};

我的测试(由于未调用模拟而无法运行):

import App from './App';

jest.mock('../services/unsplash');

it('fetches images from unsplash and renders them on mount', done => {
  const wrapper = shallow(<App />);

  setTimeout(() => {
    console.log('inside timeout App2!');
    wrapper.update();

    expect(wrapper.find('Image').length).toEqual(1);

    done();
  });
});

有人可以告诉我我在做什么错吗?我想使用自定义函数代替真正的调用。

1 个答案:

答案 0 :(得分:0)

您需要使用act()flush async events.

https://reactjs.org/docs/test-utils.html#act

也像这样进行测试async

("should blah", async () => {}

还在您的模拟中,在async await内部返回一个承诺 是多余的。使用另一个。