我可以(并且我应该)断言组件使用 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 【问题描述】:

问题:

我正在为名为@9​​87654323@ 的 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:

&lt;BaseEdit /&gt; 组件在使用 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 测试样式组件

使用钩子时 Jest/Enzyme 测试抛出错误

使用 Jest/Enzyme 在 React 功能组件中测试封闭组件

为啥 Enzyme 不从 React 组件加载样式?

如何使用 Jest 和/或 Enzyme 测试由 React 组件呈现的样式和媒体查询

使用 Jest 和 Enzyme 测试使用 Redux 的功能性 React 组件