Как проверить, установлены ли состояния в Enzyme и Jest - PullRequest
0 голосов
/ 07 февраля 2020

Я новичок в использовании Jest и Enzyme. У меня есть компонент, который устанавливает некоторые реквизиты, которые передаются из родительского компонента. В зависимости от вызова API, я хочу убедиться, что эти реквизиты установлены соответственно. В этом коде я хочу проверить, что setUser для моего user был правильно вызван. Вот мой код:

LoginButton. js

import React, { useState } from 'react';
import { useHistory } from 'react-router-dom';
import './LoginButton.css';

const LoginButton = (props) => {

  const history = useHistory();

  const [user, setUser] = useState({});

  const login = async (e) => {
    e.preventDefault();
    const loginRequest = {
      userName: props.username,
      password: props.password
    };
    try {
      const loginResponse = await fetch('/login', {
        method: 'POST',
        body: JSON.stringify(loginRequest),
        headers: {
          'Content-Type': 'application/json',
        }
      });
      const user = await loginResponse.json();
      console.log("User: ", user);
      if (user.status && user.message) {
        props.setSubmitError(user.message);
      } else if (user.userStatus && user.userStatus === "Locked" || user.userStatus === "Deactivated") {
        props.setSubmitError(user.message);
      } else {
        setUser(user);
        // TODO: do something with user, pass it to dashboard component
        history.push('/dashboard');
      }
    } catch (err) {
      props.setSubmitError(user.message);
    }
  }

  return (
    <button styleName="sign-in-btn" onClick={login}>
      Sign me in!
    </button>
  )
}

export default LoginButton; 

А вот моя попытка сделать это в LoginButton.test. js:

// mock useHistory or else it will fail in every test
jest.mock('react-router-dom', () => ({
  useHistory: () => ({
    push: jest.fn()
  })
}));

describe('LoginButton', () => {
  const setUser = jest.fn();
  const useStateSpy = jest.spyOn(React, 'useState');
  useStateSpy.mockImplementation((init) => [init, setUser]);

  it('sets user state properly', () => {

    let props = {
      setSubmitError: jest.fn()
    }

    const fakeResponse = {userName: "user123",  success: true};
    const mockJsonPromise = Promise.resolve(fakeResponse);
    const mockFetchPromise = Promise.resolve({
      json: () => {
        mockJsonPromise
      }
    });

    global.fetch = jest.fn().mockImplementation(mockFetchPromise);
    const wrapper = shallow(<LoginButton
      {...props} 
    />);
    const signInButton = wrapper.find('button')
    signInButton.simulate('click', {
      preventDefault: () => {},
    });
    expect(global.fetch).toHaveBeenCalledTimes(1);
    // here i expect setUser to have been called already.. but I get an error saying number of calls: 0
    expect(setUser).toHaveBeenCalledWith(fakeResponse);

    global.fetch.mockClear();
    delete global.fetch;

  });
})

К сожалению, я получаю сообщение о том, что setUser никогда не вызывался, и я не уверен, почему. Мне кажется, что я правильно настроил тест и, в зависимости от пройденного мной fakeResponse, считаю, что он должен go перейти в оператор m else и правильно настроить пользователя. Любая помощь будет оценена. Спасибо

1 Ответ

0 голосов
/ 07 февраля 2020

Короткий ответ: не надо.

Вам не нужно проверять setUser. Это деталь реализации и внутренняя часть компонента. Вы можете проверить, был ли вызван обратный вызов setSubmitError или history.push, если это кажется полезным (вам, вероятно, также понадобится обработчик onSuccess, чтобы передать возвращаемого пользователя, чтобы вы могли также проверить это). Но тестирование чисто внутренней реализации, такой как установщик состояний, нарушает принцип тестирования черного ящика .

Если вы действительно хотите получить этот спецификатор c при тестировании функции login, подумайте извлекать его как вспомогательную функцию, которая может быть протестирована вне контекста компонента. Это делает более ясным, каковы ожидаемые результаты для данных входных данных.

...