Reactjs 如何使用React测试库测试组件内部功能
我是测试新手,我正在尝试使用react测试库测试我的应用程序。我遇到的第一个问题是测试组件内部的函数,如事件处理程序。我发现很少有函数(事件处理程序)作为道具在组件中传递的例子,但如果可能的话,我不想这样做 我的组成部分:Reactjs 如何使用React测试库测试组件内部功能,reactjs,react-testing-library,Reactjs,React Testing Library,我是测试新手,我正在尝试使用react测试库测试我的应用程序。我遇到的第一个问题是测试组件内部的函数,如事件处理程序。我发现很少有函数(事件处理程序)作为道具在组件中传递的例子,但如果可能的话,我不想这样做 我的组成部分: import React, { useState } from 'react'; import { Redirect } from 'react-router-dom'; import { connect } from 'react-redux'; import PropTy
import React, { useState } from 'react';
import { Redirect } from 'react-router-dom';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { login } from 'actions/auth';
import Wrapper from './styled/Wrapper';
import Button from './styled/Button';
import Title from './styled/Title';
import { FormWrapper, StyledForm, FormField } from './styled/Form'
import Input from './styled/Input';
import Link from './styled/Link';
const Login = (props) => {
const [formData, setFormData] = useState({
email: '',
password: ''
});
const { email, password } = formData;
const onChange = e => setFormData({ ...formData, [e.target.name]: e.target.value });
const onSubmit = e => {
e.preventDefault();
props.login(email, password);
}
if (props.isAuthenticated) {
return <Redirect to='/' />
}
return (
<Wrapper color='#F2F2F2'>
<FormWrapper>
<Title>Log In</Title>
<StyledForm data-testid='auth-form' onSubmit={e => onSubmit(e)}>
<FormField>
<Input
placeholder='Email'
type='email'
name='email'
value={email}
onChange={e => onChange(e)}
required
/>
</FormField>
<FormField>
<Input
placeholder='Password'
type='password'
name='password'
value={password}
onChange={e => onChange(e)}
required
/>
</FormField>
<Button type='submit' marginTop='6%'>LOG IN</Button>
</StyledForm>
<p>Don't have an account? <Link to='/register'>Sign Up!</Link> </p>
</FormWrapper>
</Wrapper>
)
}
Login.propTypes = {
login: PropTypes.func.isRequired,
isAuthenticated: PropTypes.bool
}
const mapStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated
});
export default connect(mapStateToProps, { login })(Login);
import React,{useState}来自“React”;
从'react router dom'导入{Redirect};
从'react redux'导入{connect};
从“道具类型”导入道具类型;
从'actions/auth'导入{login};
从“./styled/Wrapper”导入包装器;
从“./styled/Button”导入按钮;
从“./styled/Title”导入标题;
从“./styled/Form”导入{FormWrapper,StyledForm,FormField}
从“./styled/Input”导入输入;
从“./styled/Link”导入链接;
常量登录=(道具)=>{
常量[formData,setFormData]=useState({
电子邮件:“”,
密码:“”
});
const{email,password}=formData;
const onChange=e=>setFormData({…formData[e.target.name]:e.target.value});
const onSubmit=e=>{
e、 预防默认值();
道具登录(电子邮件、密码);
}
如果(道具已验证){
返回
}
返回(
登录
onSubmit(e)}>
onChange(e)}
必修的
/>
onChange(e)}
必修的
/>
登录
没有帐户?注册吧
)
}
Login.propTypes={
登录名:PropTypes.func.isRequired,
IsAuthentication:PropTypes.bool
}
常量mapStateToProps=状态=>({
isAuthenticated:state.auth.isAuthenticated
});
导出默认连接(mapstatetops,{login})(login);
我的测试文件:
import React from 'react';
import { render, cleanup, fireEvent } from '@testing-library/react';
import { Provider } from 'react-redux';
import { BrowserRouter as Router } from 'react-router-dom';
import store from '../../store';
import Login from '../Login';
afterEach(cleanup);
const onChange = jest.fn();
test('<Login>', () => {
const { queryByTestId, getByPlaceholderText, getByText, debug } =
render(
<Provider store={store}>
<Router>
<Login />
</Router>
</Provider>);
expect(queryByTestId('auth-form')).toBeTruthy();
fireEvent.change(getByPlaceholderText('Email'), {
target: { value: 'test@yahoo.com' },
});
fireEvent.change(getByPlaceholderText('Password'), {
target: { value: 'testpassword' },
});
fireEvent.click(getByText('LOG IN'));
expect(onChange).toHaveBeenCalledTimes(1);
});
从“React”导入React;
从'@testing library/react'导入{render,cleanup,firevent};
从'react redux'导入{Provider};
从“react Router dom”导入{BrowserRouter as Router};
从“../../store”导入存储;
从“../Login”导入登录名;
每次之后(清理);
const onChange=jest.fn();
测试(“”,()=>{
常量{queryByTestId,getByPlaceholderText,getByText,debug}=
渲染(
);
expect(queryByTestId('auth-form')).toBeTruthy();
fireEvent.change(GetByPlaceholder文本(“电子邮件”){
目标:{值:'test@yahoo.com' },
});
fireEvent.change(GetByPlaceholder文本(“密码”){
目标:{value:'testpassword'},
});
firevent.click(getByText('login'));
期望(一次变更)。已被催收时间(1);
});
测试输出:
FAIL src/components/__tests__/Login.test.js
✕ <Login> (125 ms)
● <Login>
expect(jest.fn()).toHaveBeenCalledTimes(expected)
Expected number of calls: 1
Received number of calls: 0
32 |
33 | fireEvent.click(getByText('LOG IN'));
> 34 | expect(onChange).toHaveBeenCalledTimes(1);
| ^
35 |
36 | });
at Object.<anonymous>.test (src/components/__tests__/Login.test.js:34:22)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 6.013 s
Ran all test suites related to changed files.
Watch Usage: Press w to show more.
src/components/_测试失败\u_/Login.test.js
✕ (125毫秒)
●
expected(jest.fn())。toHaveBeenCalledTimes(expected)
预期呼叫数:1
收到的呼叫数:0
32 |
33 | fireEvent.单击(getByText(“登录”);
>34 |预期(一旦改变)。已被催缴的时间(1);
| ^
35 |
36 | });
at Object..test(src/components/__-tests\u_/Login.test.js:34:22)
测试套件:1个失败,共1个
测试:1次失败,共1次
快照:共0个
时间:6时01分
运行与更改的文件相关的所有测试套件。
手表用法:按w键可显示更多信息。
有没有一种方法可以使onSubmit函数在不作为道具通过测试的情况下对测试进行访问?React测试库的要点是,编写类似于用户如何使用应用程序的测试非常容易。这是我们想要实现的,以给我们充分的信心,这也是业界提倡的。我们编写测试是为了提高对应用程序的信心,而不是提高覆盖率 考虑到上述情况,您不应该使用
来调用时间
,而是应该测试触发onChange
功能的视觉结果。基于您共享的代码,我不知道成功登录后会呈现什么,但是对于我们的用例,让我们假设文本Welcome,User代码>渲染
您可以像现在一样触发事件,而不是使用haveBeenCalled
进行测试,而是使用以下方法:
expect(getByText('Welcome,User!').toBeInTheDocument();
这将为您提供充分的信心,而不是在调用某个函数时进行测试,因为如果函数的实现不正确,您将无法获得足够的信心?谢谢您的回答,很抱歉,我对我在测试中尝试执行的操作不够清楚。HavebeenCall只是为了让我获得更好的id测试失败的ea。我的目标是测试用户体验。我的onClick处理程序调用登录操作(redux)这会将请求发送到服务器并获取令牌。我需要以某种方式模拟这些函数和此响应,以便成功登录并检查之后显示的元素。对吗?如果我的操作方式错误,请纠正我。我看到您将测试组件包装在
中并注入存储区。这很好,比模拟更好的是,测试还将涵盖redux操作,这实际上是经常进行的,而不是单独编写操作、还原程序等的测试。根据您的代码和您所说的,重定向是基于身份验证的,而身份验证是基于后端的响应。您需要模拟您的响应,并在触发login、 登录页面将显示,然后可以按照我建议的方式进行断言。可以使用类似于nock
的方法模拟HTTP响应。