测试传递给 Redux HOC 的强制 PropTypes

Posted

技术标签:

【中文标题】测试传递给 Redux HOC 的强制 PropTypes【英文标题】:Testing mandatory PropTypes passed to Redux HOC's 【发布时间】:2019-04-16 11:35:32 【问题描述】:

我想编写一个测试,以确保反应组件将具有propType.isRequired 的道具传递给子组件。

如果未提供道具,我希望此测试失败,如果提供,则通过。我正在使用jest-prop-type-error 在我的测试中抛出错误。

给定以下两个组件:

Parent.js

const Parent = ( renderReduxChild , childTitle ) => 
     return renderReduxChild ? <ReduxChild title=childTitle /> : <NonReduxChild />

ReduxChild.js

const ReduxChild = ( title ) => <div>title</div>

ReduxChild.propTypes =  title: PropTypes.string.isRequired 

export default connect(mapStateToProps, mapStateToProps)(ReduxChild)

我想确保我的 Parent 组件通过 childTitle 属性,而无需编写显式测试:

Parent.test.js

it('should send the required "title" prop to ReduxChild', () => 
  const wrapper = shallow(<Parent renderReduxChild=true childTitle='expectedTitle' />)
  expect(wrapper.props().title).toBeDefined()
)

请注意以下几点:

如果 child 不是 connected 组件,我可以 notchildTitle 传递给 Parent 并且测试将失败。由于它是一个连接组件,如果我没有通过childTitle,则测试通过(即使在ReduxChild 中是必需的) 我知道这非常接近于测试PropTypes 的功能,但它的细微差别在于我想检查Parent 是否正确使用Child,而不是ReduxChild 抛出一个PropTypes未通过道具时出错。我希望测试在开发人员删除所需道具时在构建时失败,而不是在我运行代码时在运行时失败。

编辑:

为了进一步说明这个问题,如果我有第二个子组件 NonReduxChild 并给它一个 propType 其中 isRequired 并测试 Parent 渲染 NonReduxChild 而没有提供我得到的道具在构建/测试时抛出错误。 ReduxChild 我没有。

NonReduxChild.js

const NonReduxChild = ( text ) = <div>text</div>
NonReduxChild.propTypes =  text: PropTypes.string.isRequired 

测试输出

FAIL  test/components/Parent.test.js (8.782s)

● <Parent /> › when rendering the component › if renderReduxChild is false it should render <NonReduxChild />

Warning: Failed prop type: The prop `title` is marked as required in `NonReduxChild`, but its value is `undefined`.
    in NonReduxChild

  28 |   render() 
  29 |     const  renderReduxChild, childTitle  = this.state
> 30 |     return renderReduxChild ? <ReduxChild title=childTitle  /> : <NonReduxChild />
     |                                                                                                                                                                                                ^
  31 |   
  32 | 
  33 |

正如您从测试输出中看到的那样,当我没有向 NonReduxChild 提供所需的道具时,我得到一个测试失败,它很好地从其他可能不提供所需 PropTypes 的组件中捕获了 NonReduxChild 的使用情况我没有从ReduxChild 得到同样的失败我必须编写一个特定的测试(我不想在包含数百个组件的代码库中这样做)。

【问题讨论】:

不清楚为什么确保我的 Parent 组件通过 childTitle 属性而不需要编写明确的测试,说明是一项要求。这是对组件进行单元测试的正确方法。 嗯,这是因为我不想在整个大型应用程序中使用 Child 组件的每个 Parent 组件上测试每个道具。正如我在笔记中提到的,如果Child 不是connect()ed 组件,并且我的应用程序代码没有通过isRequired 属性,那么任何Parent 测试都会失败,而无需我编写显式测试。 你说得对,这可能更像是一个集成测试。我会更新标签。在单元测试方面,Child 组件确实对每个必需的道具进行了测试,因此涵盖了事物的一面。 Child 所需的未提供的 propType 将在运行时在浏览器中爆炸,而不是在我所追求的构建时爆炸,如果您愿意,我可以更新问题以演示非 redux 如何如果这样可以使事情更清晰,连接的组件会以相同的设置运行吗? 我可以更新问题以演示非 redux 连接的组件在相同设置下的行为,如果这样可以使事情更清晰? 是的,这很好。到时候我会尽量给出答案。 @estus - 我已经更新以显示 NonReduxChild 的行为方式 【参考方案1】:

我相信您遇到的问题是 PropTypes 只是记录警告,这实际上不会导致测试失败。

如果道具对组件的操作至关重要,并且您设置不编写测试来断言道具存在,那么如果该道具不存在,您总是可以让组件抛出错误。这将导致测试失败。

【讨论】:

感谢您的回复,但我使用jest-prop-type-error 在测试中抛出错误,这也没有解决父 > 子问题,也没有解决 redux 与非 redux 子差异【参考方案2】:

我认为您可以将 title 定义为 prop 并且您可以调用它,而不是 "childTitle"。 试试这个..它可能会工作

it('should send the required "title" prop to ReduxChild', () => 
`var wrapper = shallow(<Parent renderReduxChild=true title="expectedTitle" />);`
  expect(wrapper.props().title).toBeDefined()
  `console.log("",childTitle);`
)

【讨论】:

感谢您的贡献,但我不确定您的回答是否解决了问题

以上是关于测试传递给 Redux HOC 的强制 PropTypes的主要内容,如果未能解决你的问题,请参考以下文章

Jest/Enzyme 单元测试:如何将存储传递给使用 redux 4 和 react-redux 6 连接功能的浅层组件

如何将儿童类型传递给 HOC 反应的道具

如何将道具从调用组件传递给 HOC - React + Typescript

React JS:HOC(重组)或 Redux [关闭]

测试 redux 的 ConnectedComponent

在每次测试之前手动修改 initialState 并将其传递给商店?