简介
@Gajus的答案对我有所帮助,所以感谢Gajus。但是,我想提供一个更好的答案:
- 使用更新的React(v15.4.1)
- 使用React自带的Jest
- 测试单个prop的多个值
- 更通用
总结
和Gajus以及其他人建议的方法类似,我的基本方法也是确定React是否会在响应不可接受的测试prop值时使用console.error。具体来说,这种方法涉及以下每个测试prop值的操作:
- 模拟并清除
console.error
(以确保先前对console.error
的调用不会干扰),
- 使用正在考虑的测试prop值创建组件,并
- 确认是否按预期触发了
console.error
。
testPropTypes
函数
以下代码可以放在测试中或作为单独的导入/需要的模块/文件中:
const testPropTypes = (component, propName, arraysOfTestValues, otherProps) => {
console.error = jest.fn();
const _test = (testValues, expectError) => {
for (let propValue of testValues) {
console.error.mockClear();
React.createElement(component, {...otherProps, [propName]: propValue});
expect(console.error).toHaveBeenCalledTimes(expectError ? 1 : 0);
}
};
_test(arraysOfTestValues[0], false);
_test(arraysOfTestValues[1], true);
};
调用函数
任何检查propTypes
的测试都可以使用三个或四个参数来调用testPropTypes
:
component
,被该属性修改的 React组件;
propName
,被测试的属性名称的字符串;
arraysOfTestValues
,要测试的属性的所有所需测试值的数组的数组:
- 第一个子数组包含所有可接受的测试属性值,而
- 第二个子数组包含所有不可接受的测试属性值;以及
可选的,otherProps
,包含该组件其他所需属性的名称/值对的对象。
需要otherProps
对象是为了确保 React 不会因无意间缺少其他所需属性而进行无关紧要的 console.error
调用。只需为任何所需属性包括一个可接受的值,例如 {requiredPropName1: anyAcceptableValue, requiredPropName2: anyAcceptableValue}
。
函数逻辑
该函数执行以下操作:
它设置了console.error
的模拟,这是 React 用于报告类型不正确的属性的方法。
对于提供的每个测试属性值子数组,它循环遍历每个测试属性值来测试属性类型:
- 两个子数组中的第一个应该是可接受的测试属性值列表。
- 第二个子数组应为不可接受的测试属性值。
在每个单独的测试属性值的循环中,首先清除console.error
模拟,以便可以假定检测到的任何错误消息来自此测试。
然后,使用测试属性值和当前未测试的任何其他所需属性之一创建组件实例。
最后,检查是否已触发警告,如果您的测试尝试使用不合适或丢失的属性创建组件,则应该会发生这种情况。
测试可选和必需属性
请注意,将null
(或undefined
)分配给属性值从React的角度来看与不为该属性提供任何值本质上相同。定义上,这对于可选的 prop 是可接受的,但对于必需的 prop 是不可接受的。因此,通过将null
放入可接受或不可接受值的任一数组中,您可以测试该属性是可选还是必需。
示例代码
MyComponent.js(仅包含propTypes
):
MyComponent.propTypes = {
myProp1: React.PropTypes.number,
myProp2: React.PropTypes.oneOfType([
React.PropTypes.number,
React.PropTypes.arrayOf(React.PropTypes.number)
]).isRequired
MyComponent.test.js:
describe('MyComponent', () => {
it('should accept an optional number for myProp1', () => {
const testValues = [
[0, null],
['', []]
];
testPropTypes(MyComponent, 'myProp1', testValues, {myProp2: 123});
});
it('should require a number or an array of numbers for myProp2', () => {
const testValues = [
[0, [0]],
['', null]
];
testPropTypes(MyComponent, 'myProp2', testValues);
});
});
该方法的局限性(重要)
目前对于这种方法有一些显著的限制,如果超出限制,可能是一些难以追踪的测试错误的来源。这些限制的原因和影响在另一个SO问题/答案中有解释。简而言之,对于像myProp1
这样的简单属性类型,可以测试多个不可接受的非null
测试属性值,只要它们都是不同的数据类型。对于某些复杂的属性类型(例如myProp2
),只能测试任意类型的单个不可接受的非null
属性值。请参阅其他问题/答案进行更深入的讨论。
PropType
吗?我通过监听console.warn
来测试我的。 - srphNODE_ENV=development
能解决问题吗? - Patrick Burtchaell