#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». Я не могу придумать, как высмеять этот первый аргумент, есть идеи??