我可以(并且我应该)断言组件使用 Enzyme 的 shallow() 渲染了哪些 HTML 元素吗?
Posted
技术标签:
【中文标题】我可以(并且我应该)断言组件使用 Enzyme 的 shallow() 渲染了哪些 HTML 元素吗?【英文标题】:Can I, (and should I), make assertions about what HTML elements a component renders using Enzyme's shallow()? 【发布时间】:2019-12-22 04:53:23 【问题描述】:问题:
我正在为名为@987654323@ 的 React 组件编写单元测试。为了测试组件是否工作,我想断言它将呈现一个 html 元素 <input/>
,并且我想使用 shallow() 而不是 mount()。
以下测试用例有效:
const baseEditWrapper = mount(<BaseEdit />)
const inputElement = baseEditWrapper.find('input')
assert(inputElement.exists())
assert.strictEqual(inputElement.prop('type'), 'text')
但是,如果我将mount()
更改为shallow()
,则测试失败。它失败了,因为 baseEditWrapper.find('input')
返回一个空/存根/不存在的 ShallowWrapper 对象。
底层 HTML:
<BaseEdit />
组件在使用 Enzyme 和 JSDom 挂载时,会创建以下 DOM 元素。
<div class="MuiFormControl-root MuiTextField-root WithStyles(ForwardRef(TextField))-root-27 WithStyles(ForwardRef(TextField))-root-96" style="width:120px">
<div class="MuiInputBase-root MuiInput-root MuiInput-underline MuiInputBase-formControl MuiInput-formControl">
<input type="text" aria-invalid="false" class="MuiInputBase-input MuiInput-input"/>
</div>
</div>
额外细节:
shallow() 的文档是 here。
问题when should you use render and shallow in enzyme react tests? 表明使用 shallow() 时支持通过选择器查找。
下面的测试用例证明了 shallow 确实渲染了多层 HTML 元素,并且可以作为我的问题的解决方案。
const shallowWrapper = shallow(<BaseEdit />)
assert(shallowWrapper.html().includes('<input')
assert(shallowWrapper.html().includes('type=\"text\"'))
然而,这样的解决方案似乎很老套,我宁愿让我的解决方案与 Enzyme 的 ShallowWrapper
接口的使用保持一致。
【问题讨论】:
【参考方案1】:您应该可以使用.dive()
来查找输入:
const input = wrapper.find(TextField).dive().find('input')
如果input
嵌套在多个 React 组件中,您甚至可能需要多次潜水:
// This is a little contrived, but something like this:
const InnerTextField = () => <input />;
const TextField = () => <InnerTextField />;
const BaseEdit = () => <TextField />;
// You would need to do this to find the input:
const input = wrapper.find(TextField).dive().dive().find('input');
你还问过你是否应该使用shallow
:
如果您想对底层 HTML 进行断言(例如,您想确保 BaseEdit
始终呈现 input
),您最好使用 mount
,除非有理由不这样做.
shallow
在您想要测试组件树的单层时很有用。看起来您正在使用 Material UI,因此可能的测试可能是检查 BaseEdit
是否将道具正确传递给 TextField
。
it('passes the required prop to the underlying component', () =>
const wrapper = shallow(<BaseEdit required />);
expect(wrapper.find(TextEdit).props().required).toBe(true);
wrapper.setProps( required: false );
expect(wrapper.find(TextEdit).props().required).toBe(false);
)
【讨论】:
感谢您的洞察力。使用dive() 感觉比检查HTML 更严格,所以我决定只使用mount() 来处理所有事情。最大的原因是 mount() 与 shallow() 在毫秒级别上产生了差异,而运行整个 mocha 测试套件(包括加载节点然后加载所有模块的过程)需要几分钟。我发现这两篇文章对于探讨 shallow() 和 mount() 之间的争论很有趣:kentcdodds.com/blog/why-i-never-use-shallow-rendering, hackernoon.com/why-i-always-use-shallow-rendering-a3a50da60942 听起来不错!关于浅层与安装有很多争论,IMO 它们都有自己的用途,只是用于不同类型的测试。很高兴我能帮上忙!以上是关于我可以(并且我应该)断言组件使用 Enzyme 的 shallow() 渲染了哪些 HTML 元素吗?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Jest/Enzyme 在 React 功能组件中测试封闭组件