Как смоделировать API для функционального компонента React без состояния? - PullRequest
1 голос
/ 30 октября 2019

Я пытаюсь протестировать компонент Stateless Functional React, который выполняет вызов Fetch во время ловушки жизненного цикла useEffect. Я хотел бы создать макет 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;

My Mock Service (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);
  });
};

Мой тест (не работает, поскольку mock не вызывается):

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 голосов
/ 30 октября 2019

Вам необходимо использовать act() до flush async events.

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

Также сделайте свой тест async таким, как он

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

Также втвоя насмешка, возвращающая обещание внутри async await, излишня. Используйте один или другой.

...