【发布时间】:2020-10-01 01:48:53
【问题描述】:
我正在尝试执行一个简单的单元测试以确认我的Register 组件呈现.container。我认为这可能是shallow 的级别/层次结构问题,或者可能是渲染问题,但我不能确定。
以下是我的Register 组件。
import React, { useState } from 'react';
import { Link, Redirect } from 'react-router-dom';
//redux
import { connect } from 'react-redux';
import { setAlert } from '../../actions/alert';
import { register } from '../../actions/auth';
import PropTypes from 'prop-types';
const Register = ({ setAlert, register, authState: { isAuthenticated } }) => {
//...
if (isAuthenticated) {
return <Redirect to='/dashboard' />;
}
return (
<section className='container'> <====== I want to verify this container so I can do further testing by calling find('input') on the container.
<h1 className='large text-primary'>Sign up</h1>
<p className='lead'>
<i className='fas fa-user-circle'> Create Your Account</i>
</p>
<form onSubmit={handleSubmit} className='form'>
<div className='form-group'>
<input
type='text'
placeholder='Name'
value={name}
onChange={e => handleNameChange(e)}
required
/>
</div>
//...
</section>
Register.propTypes = {
setAlert: PropTypes.func.isRequired,
register: PropTypes.func.isRequired,
authState: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
authState: state.auth
});
export default connect(mapStateToProps, { setAlert, register })(Register);
这是我的 App 组件,它显示了我的应用程序的层次结构:
const App = () => {
useEffect(() => {
if (localStorage.token) {
setAuthToken(localStorage.token);
store.dispatch(loadUser());
}
}, []);
return (
<Provider store={store}>
<Router>
<Fragment>
<Navbar />
<Route exact path='/' component={Landing} />
<section className='container'>
<Alert />
<Switch>
<Route exact path='/Register' component={Register} />
<Route exact path='/Login' component={Login} />
//...
</Provider>
);
export default App;
以下是我的测试文件,以及我所有尝试使用dive() 是否处于正确级别,或使用不同的酶方法,如find()、hasClass() 等。
我尝试在渲染期间显式传递组件所需的道具,并将它们作为我的模拟商店的初始状态传递。
import React from 'react';
import { shallow } from 'enzyme';
import toJson from 'enzyme-to-json';
import configureMockStore from 'redux-mock-store';
import { Provider } from 'react-redux'; store
// Component to be tested
import Register from '../../../src/components/auth/Register';
// Props for the Register component
import { setAlert } from '../../../src/actions/alert';
import { register } from '../../../src/actions/auth';
// Mock Store
const mockStore = configureMockStore();
const store = mockStore({
setAlert: setAlert,
register: register,
authState: {
isAuthenticated: false,
loading: false,
},
});
describe('<Register /> component renders a <section> with className container.', () => {
let props;
beforeEach(() => {
props = {
setAlert: setAlert,
register: register,
authState: {
token: localStorage.getItem('token'),
isAuthenticated: false,
loading: false,
loggedInUser: null,
},
};
});
test("Attempt #1: No dive() and .find('section')", () => {
const wrapper = shallow(
<Provider store={store}>
<Register {...props} />
</Provider>
);
const section = wrapper.find('section');
expect(section.length).toBe(1); // Section.length returns 0
});
test("Attempt #2: Use dive() and .find('section')", () => {
const wrapper = shallow(
<Provider store={store}>
<Register {...props} />
</Provider>
).dive();
const section = wrapper.find('section');
expect(section.length).toBe(1); // Section.length returns 0
});
test("Attempt #3: No dive() and .hasClass('container')", () => {
const wrapper = shallow(
<Provider store={store}>
<Register {...props} />
</Provider>
);
expect(wrapper.hasClass('container')).toEqual(true); // hasClass returns false
});
test("Attempt #4: Use dive() and .hasClass('container')", () => {
const wrapper = shallow(
<Provider store={store}>
<Register {...props} />
</Provider>
).dive();
expect(wrapper.hasClass('container')).toEqual(true); // hasClass returns false
});
test('Attempt #5: No dive() and .to.have.lengthOf(1)', () => {
const wrapper = shallow(
<Provider store={store}>
<Register {...props} />
</Provider>
);
expect(wrapper.find('.container')).to.have.lengthOf(1); // Can't read property have of undefined
});
test('Attempt #6: Use dive() and .to.have.lengthOf(1)', () => {
const wrapper = shallow(
<Provider store={store}>
<Register {...props} />
</Provider>
).dive();
expect(wrapper.find('.container')).to.have.lengthOf(1); // Can't read property of undefined
});
});
以下是wrapper.debug()的输出:
// The wrapper without dive()
<ContextProvider value={{ store: { getState: [Function: getState], getActions: [Function: getActions], dispatch: [Function: dispatch], clearActions: [Function: clearActions], subscribe: [Function: subscribe], replaceReducer: [Function: replaceReducer] }, subscription: { store: { getState: [Function: getState], getActions: [Function: getActions], dispatch: [Function: dispatch], clearActions: [Function: clearActions], subscribe: [Function: subscribe], replaceReducer: [Function: replaceReducer] }, parentSub: undefined, unsubscribe: null, listeners: { notify: [Function: notify] }, handleChangeWrapper: [Function: bound handleChangeWrapper], onStateChange: [Function: notifyNestedSubs] } }}>
<Connect(Register) setAlert={[Function: setAlert]} register={[Function: register]} authState={{ token: null, isAuthenticated: false, loading: false, loggedInUser: null }} />
</ContextProvider>
// The Wrapper using dive():
<Connect(Register) setAlert={[Function: setAlert]} register={[Function: register]} authState={{ token: null, isAuthenticated: false, loading: false, loggedInUser: null }} />
我所有的尝试要么返回 0 个节点,要么返回 false。我看的不是正确的水平吗?每次尝试是否都因潜在的缺少 prop 要求而失败,该要求未能尝试呈现组件?
以下是我的 repo 的链接,在分支 test-component-help 下:
以及相关文件的位置:
测试文件:./client/__tests__/components/auth/Register.test.js
组件:./client/src/components/auth/Register.js
【问题讨论】:
-
你能控制台记录你的
isAuthenticated吗?也许控制没有到达您的渲染并在重定向时返回。 -
我在
shallow()调用之后添加了console.log(props.authState.isAuthenticated),它输出false。这是检查isAuthenticated状态的正确方法吗? -
您应该在组件本身而不是在测试文件中添加该日志行。就在您的
if(isAuthenticated)行之前。 -
我在我的组件中添加了
console.log,但是当我运行我的测试文件时,没有输出。这让我相信组件没有被渲染。但是,我在shallow调用之后检查了wrapper的长度,它返回1。这是否意味着组件已呈现?如果是这样,为什么console.log没有被执行? -
您的测试脚本
test: jest --silent可能有 --silent 标志?也可以尝试安装并记录包装器调试 API 输出。如果这没有帮助,请在 GitHub 上放置一个指向您项目的链接。如果可以的话,可以看看并做出贡献。
标签: reactjs redux jestjs components enzyme