Reactjs TypeError:无法读取属性';电子邮件';使用玩笑和反应的未定义道具。为什么?
尝试使用Jest为ReactJs代码编写单元测试。当我试图通过道具时,它会在下面显示错误 TypeError:无法读取未定义的属性“email”Reactjs TypeError:无法读取属性';电子邮件';使用玩笑和反应的未定义道具。为什么?,reactjs,jestjs,babel-jest,Reactjs,Jestjs,Babel Jest,尝试使用Jest为ReactJs代码编写单元测试。当我试图通过道具时,它会在下面显示错误 TypeError:无法读取未定义的属性“email” 62 | 63 | const mapStateToProps = state => { > 64 | const { email, password, errors, loading } = state.auth; | ^ 65 | 66 | return { email, pas
62 |
63 | const mapStateToProps = state => {
> 64 | const { email, password, errors, loading } = state.auth;
| ^
65 |
66 | return { email, password, errors, loading };
67 | };
签名
import React, { Component } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import * as actions from "Actions";
import classnames from "classnames";
class SignIn extends Component {
onSubmit(e) {
e.preventDefault();
const { email, password } = this.props;
this.props.loginUser({ email, password });
}
render() {
const { email, password, errors, fieldChanged } = this.props;
return (
<div className="contentWrapper">
....
</div>
);
}
}
SignIn.propTypes = {
loginUser: PropTypes.func.isRequired,
fieldChanged: PropTypes.func.isRequired,
email: PropTypes.string.isRequired,
password: PropTypes.string.isRequired
};
const mapStateToProps = state => {
const { email, password, errors, loading } = state.auth;
return { email, password, errors, loading };
};
export default connect(
mapStateToProps,
actions
)(SignIn);
import React,{Component}来自“React”;
从“道具类型”导入道具类型;
从“react redux”导入{connect};
从“react router dom”导入{Link};
从“操作”导入*作为操作;
从“类名”中导入类名;
类签名扩展组件{
提交(e){
e、 预防默认值();
const{email,password}=this.props;
this.props.logiuser({email,password});
}
render(){
const{email,password,errors,fieldChanged}=this.props;
返回(
....
);
}
}
签名类型={
登录用户:需要PropTypes.func.isRequired,
字段更改:需要PropTypes.func.isRequired,
电子邮件:PropTypes.string.isRequired,
密码:PropTypes.string.isRequired
};
常量mapStateToProps=状态=>{
const{email,密码,错误,loading}=state.auth;
返回{电子邮件、密码、错误、加载};
};
导出默认连接(
MapStateTops,
行动
)(签名);
SignIn.test.js
import React, { Suspense } from 'react';
import Enzyme, {shallow} from 'enzyme';
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-15';
Enzyme.configure({ adapter: new Adapter() });
import { Provider } from 'react-redux';
import configureMockStore from "redux-mock-store";
import thunk from 'redux-thunk';
import SignIn from '../containers/authentication/SignIn';
import mapStateToProps from "../containers/authentication/SignIn";
const mockStore = configureMockStore();
describe('SignIn', () => {
it('render sign in', () => {
const state = {
email: "aaky8668@gmail.com",
password: "pass123"
};
const store = mockStore(state);
const dwrapper = Enzyme.mount(<SignIn store={store} />);
console.log(dwrapper);
expect(dwrapper.props().email).toBe("aakshay8668@gmail.com")
});
});
import React,{suspend}来自'React';
输入酶,{shall}来自“酶”;
从“酶”导入{configure};
从'enzyme-Adapter-react-15'导入适配器;
configure({adapter:newadapter()});
从'react redux'导入{Provider};
从“redux模拟存储”导入configureMockStore;
从“redux thunk”导入thunk;
从“../containers/authentication/SignIn”导入登录;
从“./containers/authentication/SignIn”导入MapStateTrops;
const mockStore=configureMockStore();
描述('签名',()=>{
它('呈现登录',()=>{
常量状态={
电子邮件:“aaky8668@gmail.com",
密码:“pass123”
};
常量存储=模拟存储(状态);
const dwrapper=Enzyme.mount();
控制台日志(dwrapper);
期望(dwrapper.props().email).toBe(“aakshay8668@gmail.com")
});
});
需要单元测试登录并获得此错误,如何使用道具映射状态
使用道具映射状态的正确方法是什么
const { email, password, errors, loading } = state.auth;
正在尝试解构状态。auth
,它尝试将其电子邮件
,密码
,错误
,加载到同名变量中。错误表示
状态。auth
未定义。您需要确保该状态存在,它有一个auth
成员,该成员具有上述代码所期望的名称的属性。行
const { email, password, errors, loading } = state.auth;
正在尝试解构状态。auth
,它尝试将其电子邮件
,密码
,错误
,加载到同名变量中。错误表示
状态。auth
未定义。您需要确保该状态存在,它有一个auth
成员,该成员具有上述代码所期望的名称属性。我支持绕过redux部分,独立地针对操作和还原程序进行测试。因此,我建议导出类
并将其导入测试
工作示例(单击测试
选项卡以运行测试):
容器/Login/index.js
import React, { Component, Fragment } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { login } from "../../actions/Auth";
import Form from "../../components/Form";
import SubTitle from "../../components/SubTitle";
import Title from "../../components/Title";
export class Login extends Component {
state = {
email: "",
password: ""
};
handleChange = ({ target: { name, value } }) =>
this.setState({ [name]: value });
handleSubmit = e => {
e.preventDefault();
const { email, password } = this.state;
if (!email || !password) return;
this.props.login(email);
};
render = () => (
<Fragment>
<Title>Login</Title>
<SubTitle>You must login before viewing the dashboard!</SubTitle>
<Form onSubmit={this.handleSubmit}>
<input
name="email"
type="email"
className="uk-input"
placeholder="email"
value={this.state.email}
onChange={this.handleChange}
/>
<input
className="uk-input"
name="password"
type="password"
placeholder="password"
value={this.state.password}
onChange={this.handleChange}
/>
<br />
<button className="uk-button uk-button-primary" type="submit">
Login
</button>
</Form>
</Fragment>
);
}
Login.propTypes = {
login: PropTypes.func.isRequired
};
export default connect(
null,
{ login }
)(Login);
import React from "react";
import { mount } from "enzyme";
import { Login } from "../index";
const login = jest.fn();
const initProps = {
login
};
describe("Login", () => {
let wrapper;
beforeEach(() => {
wrapper = mount(<Login {...initProps} />);
});
afterEach(() => {
login.mockClear();
});
it("renders without errors", () => {
expect(wrapper.find("form").exists()).toBeTruthy();
});
it("calls handleChange class field to update an input with a value", () => {
const value = "test@test.com";
wrapper
.find("input")
.first()
.simulate("change", { target: { value, name: "email" } });
expect(wrapper.state("email")).toEqual(value);
expect(
wrapper
.find("input")
.first()
.props().value
).toEqual(value);
});
it("doesn't call 'login' prop if email or password fields are empty", () => {
wrapper.find("form").simulate("submit");
expect(login).toHaveBeenCalledTimes(0);
});
it("calls 'login' prop to log in a user", () => {
const email = "test@test.com";
wrapper.setState({ email, password: "password" });
wrapper.find("form").simulate("submit");
expect(login).toHaveBeenCalledWith(email);
});
});
import React,{Component,Fragment}来自“React”;
从“道具类型”导入道具类型;
从“react redux”导入{connect};
从“../../actions/Auth”导入{login};
从“../../components/Form”导入表单;
从“../../components/SubTitle”导入字幕;
从“../../components/Title”导入标题;
导出类登录扩展组件{
状态={
电邮:“,
密码:“
};
handleChange=({target:{name,value}})=>
this.setState({[name]:value});
handleSubmit=e=>{
e、 预防默认值();
const{email,password}=this.state;
如果(!email | |!password)返回;
此.props.login(电子邮件);
};
渲染=()=>(
登录
您必须先登录才能查看仪表板!
登录
);
}
Login.propTypes={
登录名:PropTypes.func.isRequired
};
导出默认连接(
无效的
{login}
)(登入);
容器/Login/\uuuuu测试/Login.test.js
import React, { Component, Fragment } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { login } from "../../actions/Auth";
import Form from "../../components/Form";
import SubTitle from "../../components/SubTitle";
import Title from "../../components/Title";
export class Login extends Component {
state = {
email: "",
password: ""
};
handleChange = ({ target: { name, value } }) =>
this.setState({ [name]: value });
handleSubmit = e => {
e.preventDefault();
const { email, password } = this.state;
if (!email || !password) return;
this.props.login(email);
};
render = () => (
<Fragment>
<Title>Login</Title>
<SubTitle>You must login before viewing the dashboard!</SubTitle>
<Form onSubmit={this.handleSubmit}>
<input
name="email"
type="email"
className="uk-input"
placeholder="email"
value={this.state.email}
onChange={this.handleChange}
/>
<input
className="uk-input"
name="password"
type="password"
placeholder="password"
value={this.state.password}
onChange={this.handleChange}
/>
<br />
<button className="uk-button uk-button-primary" type="submit">
Login
</button>
</Form>
</Fragment>
);
}
Login.propTypes = {
login: PropTypes.func.isRequired
};
export default connect(
null,
{ login }
)(Login);
import React from "react";
import { mount } from "enzyme";
import { Login } from "../index";
const login = jest.fn();
const initProps = {
login
};
describe("Login", () => {
let wrapper;
beforeEach(() => {
wrapper = mount(<Login {...initProps} />);
});
afterEach(() => {
login.mockClear();
});
it("renders without errors", () => {
expect(wrapper.find("form").exists()).toBeTruthy();
});
it("calls handleChange class field to update an input with a value", () => {
const value = "test@test.com";
wrapper
.find("input")
.first()
.simulate("change", { target: { value, name: "email" } });
expect(wrapper.state("email")).toEqual(value);
expect(
wrapper
.find("input")
.first()
.props().value
).toEqual(value);
});
it("doesn't call 'login' prop if email or password fields are empty", () => {
wrapper.find("form").simulate("submit");
expect(login).toHaveBeenCalledTimes(0);
});
it("calls 'login' prop to log in a user", () => {
const email = "test@test.com";
wrapper.setState({ email, password: "password" });
wrapper.find("form").simulate("submit");
expect(login).toHaveBeenCalledWith(email);
});
});
从“React”导入React;
从“酶”导入{mount};
从“./索引”导入{Login};
const login=jest.fn();
常量initProps={
登录
};
描述(“登录”,()=>{
让包装纸;
在每个之前(()=>{
包装器=mount();
});
之后(()=>{
login.mockClear();
});
它(“呈现时没有错误”,()=>{
expect(wrapper.find(“form”).exists()).toBeTruthy();
});
它(“调用handleChange类字段以使用值更新输入”,()=>{
常量值=”test@test.com";
包装纸
.find(“输入”)
.first()
.simulate(“更改”{target:{value,name:“email”}});
expect(wrapper.state(“email”)).toEqual(value);
期待(
包装纸
.find(“输入”)
.first()
.props()值
).toEqual(价值);
});
它(“如果电子邮件或密码字段为空,则不调用'login'属性”,()=>{
包装器。查找(“表单”)。模拟(“提交”);
期望(登录).toHaveBeenCalledTimes(0);
});
它(“调用‘login’prop来登录用户”,()=>{
常量电子邮件=”test@test.com";
setState({email,password:“password”});
包装器。查找(“表单”)。模拟(“提交”);
期望(登录)。已通过(电子邮件)访问;
});
});
我支持绕过redux部分,独立测试操作
和减缩器
。因此,我建议导出类