Тестирование формы входа в систему с помощью jest и библиотеки тестирования реакций

#reactjs #testing #jestjs #react-testing-library

Вопрос:

У меня есть эта форма входа в систему в react:

 import React from 'react'; import {  Card,CardBody,Container,Form,FormGroup,Label,Input,Button,Col,Row,UncontrolledAlert } from 'reactstrap'; import { AuthLogin, AuthContext } from '../API/auth'; import { InputType } from 'reactstrap/es/Input';  function useInput(type: InputType): [string, JSX.Element] {  const [value, setValue] = React.useState("");  const inputId = type === "text" ? "username" : "password";  const input = lt;Input id={inputId} value={value} type={type} onChange={e =gt; setValue(e.target.value)} /gt;;  return [value, input]; }   export default function Login() {  const { state, dispatch } = React.useContext(AuthContext);  const [username, usernameInput] = useInput("text");  const [password, passwordInput] = useInput("password");   const failureMessage = () =gt; {  if (state.login_error) {  return (  lt;UncontrolledAlert color="danger"gt;  Login failed: {state.login_error}  lt;/UncontrolledAlertgt;  )   }  };   const submitDisabled = () =gt; username.length === 0 || password.length === 0;   const handleSubmit = (e: React.FormEventlt;HTMLFormElementgt;) =gt; {  const doLogin = async () =gt; {  await AuthLogin(dispatch, username, password);  };   e.preventDefault()  doLogin();  }   return (  lt;divgt;  lt;Containergt;  lt;Rowgt;  lt;Colgt;lt;h1gt;Loginlt;/h1gt;lt;/Colgt;  lt;/Rowgt;  {failureMessage()}  lt;Card className="login"gt;  lt;CardBodygt;  lt;Form onSubmit={handleSubmit}gt;  lt;FormGroup rowgt;  lt;Label for='username' sm={2}gt;Usernamelt;/Labelgt;  lt;Col sm={12}gt;  {usernameInput}  lt;/Colgt;  lt;/FormGroupgt;  lt;FormGroup rowgt;  lt;Label for='password' sm={2}gt;Passwordlt;/Labelgt;  lt;Col sm={12}gt;  {passwordInput}  lt;/Colgt;  lt;/FormGroupgt;  lt;Button type="submit" disabled={submitDisabled()}gt;Log inlt;/Buttongt;  lt;/Formgt;  lt;/CardBodygt;  lt;/Cardgt;  lt;/Containergt;  lt;/divgt;  ); }  

И я хочу протестировать аутентификацию в своем интерфейсном тестировании. Вот один (проходной) тест, который я написал:

 test('submits username and password', async () =gt; {   // ARRANGE  const username = "myusername";  const password = "pass1234";  const mockLogin = jest.fn();   render(lt;Login onSubmit={mockLogin(username, password)} /gt;);   const usernameInput = screen.getByRole('textbox', { name: /Username/i });  userEvent.type(usernameInput, 'myusername');  const passwordInput = screen.getByLabelText('Password');  userEvent.type(passwordInput, 'pass1234');  const loginButton = screen.getByRole('button', { name: /^Log in$/i });  expect(loginButton).not.toBeDisabled();   // ACT  userEvent.click(loginButton);   // ASSERT  await expect(mockLogin).toHaveBeenCalled();  await expect(mockLogin).toHaveBeenCalledTimes(1);  await expect(mockLogin).toHaveBeenCalledWith("myusername", "pass1234");  });  });  

Я новичок в реагировании и в этих конкретных фреймворках тестирования интерфейса, поэтому мои вопросы носят более концептуальный характер:

  • должен ли я тестировать фактическую реализацию аутентификации (а также издеваться)? (учитывая, что модульные тесты промежуточного программного обеспечения делают это в любом случае)
  • если да, то как мне этого добиться — когда я не издеваюсь, я, похоже, не могу отправить форму (если только я не неправильно понимаю обратную связь — когда я показываю.debug (), я все еще вижу форму входа, а не аутентифицированную страницу или ошибку входа).
  • насмешки в этом случае, похоже, не доказывают ничего, кроме возможности насмешек — я не уверен, что вижу в этом смысл, кроме того, что ожидаемые элементы находятся на странице и включены/отключены, когда это уместно. В этом ли дело?

Спасибо за вашу помощь.

Комментарии:

1. Не пытаюсь ответить на ваш вопрос, но ваш тест, возможно, проходит, но он не проверяет правильную вещь. handleSubmit Функция является внутренней функцией, и Login компонент не принимает никаких реквизитов. onSubmit Опора, которую вы проходите в тесте, не существует в реальном компоненте. Ваши утверждения подтверждают то, что вы вызываете mockLogin сам тест, когда передаете его в качестве опоры: mockLogin(username, password) .

2. Спасибо @juliomalves, я понимаю, о чем вы говорите, и это имеет смысл — я согласен, что это неправильное тестирование. Так что мне каким-то образом нужно уметь издеваться над реальной функцией handleSubmit, это тот подход, который я должен здесь использовать? Если да, то какие-нибудь указания о том, как это сделать?

3. Вы не можете издеваться над handleSubmit функцией, поскольку она является внутренней для компонента. Однако вы можете издеваться AuthLogin над тем, что называется handleSubmit , и утверждать , что это называется с правильными параметрами.

4. Еще раз спасибо @juliomalves. Таким образом, AuthLogin выглядит следующим образом: экспорт const AuthLogin = асинхронный (отправка: Реагирует. Отправкаlt;AuthActiongt;, имя пользователя: строка, пароль: строка) =lt;AuthActiongt;gt; {… . Если я буду так издеваться: ожидайте(авт. AuthLogin). toHaveBeenCalledWith(mockDispatch, «Имя пользователя», «pass1234»);, я получаю следующую ошибку: Ожидается: [Функция mockConstructor], «Имя пользователя», «pass1234» Получено: [Отправка функции], «Имя пользователя», «pass1234». Я не могу придумать, как высмеять этот первый аргумент, есть идеи??