如何在Jest与Enzyme中验证React Props?Button测试失败原因求解
我正在学习React测试,现在有Button.js、Button.test.js和StyledButton.js三个文件。问题是:当我不在Button组件里把text props传递给StyledButton时,测试总是失败,提示Expected value to be: "Join us" Received: undefined,但明明Button组件已经接收了text props并把它作为子元素渲染了。以下是我的代码:
Button.js
import React from 'react'; import { string, bool, func } from 'prop-types'; import { StyledButton } from './styled' const Button = ({ size, text, }) => ( <StyledButton size={size} // 测试总是失败,除非我加上下面这行 // text={text} > {text} // 我已经在这里把text作为子元素传递了,哪里出错了? </StyledButton> ); Button.propTypes = { size: string, text: string, }; Button.defaultProps = { size: '', text: '', }; export default Button;
Button.test.js
import React from 'react'; import { shallow } from 'enzyme'; import Button from '../../components/Button/Button'; describe('Component: Button', () => { const minProps = { text: '', size: '', }; it('renders a button in size of "small" with text in it', () => { const wrapper = shallow( <Button {...minProps} size="small" text="Join us" /> ); expect(wrapper.prop('size')).toBe('small'); expect(wrapper.prop('text')).toBe('Join us'); // 这里是失败的地方 }); });
StyledButton.js
import Button from 'antd/lib/button'; const StyledButton = styled(Button)` &.ant-btn { padding: 0 24px; ${({ size }) => { if (size === 'small') { return css` font-size: 14px; line-height: 32px; `; } return null; }}; `; export { StyledButton };
问题出在哪?
这是个很常见的Enzyme使用误区,我来帮你理清楚:
你误解了wrapper.prop()方法的作用对象:当你用shallow()渲染Button组件时,返回的wrapper指向的是**Button组件最终渲染出的根元素(也就是StyledButton)**,而不是Button组件本身。
所以你写的expect(wrapper.prop('text')),实际上是在检查StyledButton有没有收到text这个props,而不是检查Button组件是否接收到了text。
你的Button组件确实拿到了text props,也把它作为子元素渲染到了StyledButton里,但子元素属于children props,和单独的text props是完全两回事——你没把text作为独立props传给StyledButton,那它的props里自然没有text,测试就会返回undefined。
怎么修复?
根据你的测试目标,有两种合理的修正方式:
1. 如果你的测试是想验证Button把text传递给了StyledButton
那保持当前测试逻辑,同时在Button里把text作为props传给StyledButton就行:
<StyledButton size={size} text={text}> {text} </StyledButton>
不过要注意:Ant Design的原生Button组件并不接收text props,它是通过子元素显示文本的,所以这种传递其实是多余的——除非你在StyledButton里自己扩展了这个props的逻辑。
2. 如果你的测试是想验证Button正确渲染了文本内容(更合理的目标)
这才是测试按钮组件的核心逻辑:确保它能显示传入的文本。你应该用wrapper.text()来获取渲染后的实际文本,而不是检查text props:
it('renders a button in size of "small" with text in it', () => { const wrapper = shallow( <Button {...minProps} size="small" text="Join us" /> ); expect(wrapper.prop('size')).toBe('small'); expect(wrapper.text()).toBe('Join us'); // 改成检查渲染出的文本 });
这样就算你不把text作为props传给StyledButton,测试也能正常通过——因为wrapper.text()会读取StyledButton渲染出的子元素文本,这正是你想要验证的结果。
内容的提问来源于stack exchange,提问作者vizFlux

