问题
Trying to write unit tests for the ReactJs code using Jest. When I am trying to pass the props it shows me below error
TypeError: Cannot read property 'email' of undefined
62 |
63 | const mapStateToProps = state => {
> 64 | const { email, password, errors, loading } = state.auth;
| ^
65 |
66 | return { email, password, errors, loading };
67 | };
SignIn.js
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);
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")
});
});
Need to unit test SignIn and getting this error, how to map state with props?
What will be the correct way to map state with props.
回答1:
The line of
const { email, password, errors, loading } = state.auth;
is attempting to destructure state.auth
, it attempts to store its email
, password
, errors
, loading
members into variables with the same names. The error indicates that
state.auth
is undefined
. You will need to make sure that state exists, it has an auth
member which has attributes of the names that your code above expects.
回答2:
I'm a proponent of bypassing the redux portion and testing against actions
and reducers
independently. Therefore, I'd recommend exporting the class
and importing that for your test.
Working example (click the Tests
tab to run tests):
containers/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);
containers/Login/__tests__/Login.test.js
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);
});
});
回答3:
SignIn.test.js
The key too solution is that we have to add dive() to the shallow component so that it could get the component wrapper completely, this solution worked for me
import React, { Suspense } from 'react';
import Enzyme, { shallow, configur } from 'enzyme';
import EnzymeAdapter from 'enzyme-adapter-react-15';
import SignIn from '../containers/authentication/SignIn';
import configureStore from '../configureStore';
Enzyme.configure({
adapter: new EnzymeAdapter(),
disableLifecycleMethods: true
});
describe('SignIn', () => {
it('render sign in', () => {
const state = {
auth: {
email: "test@test.com",
password: "password",
errors: {
login: "red"
},
loading: true
}
};
const store = configureStore(state);
const dwrapper = shallow(<SignIn store={store}/>).dive();
expect(dwrapper.find(".contentWrapper").exists()).toBeTruthy();
});
});
来源:https://stackoverflow.com/questions/59446441/typeerror-cannot-read-property-email-of-undefined-props-using-jest-and-react