当前位置: 首页 > 面试题库 >

为什么当我使用多个不可接受的prop值时,我对React propTypes的Jest测试会中断?

舒赞
2023-03-14
问题内容

在回答有关如何propTypes使用Jest在React中进行测试的另一个SO问题时,我提出了一个可模拟的解决方案console.error,这是其他人以前做过的,但我认为可以改进。我的解决方案是一个函数,如下。下面的示例代码包含一些任意代码propTypes,然后对其进行测试。对于每个测试,我希望“可接受值”的第一个子数组不会引起console.errorReact调用该模拟,但是我希望“不可接受值”的第二个子数组中的每个测试道具值导致被嘲笑。

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);
};

范例程式码

MyComponent.js(只是propTypes):

MyComponent.propTypes = {
    myProp1: React.PropTypes.number,      // optional number
    myProp2: React.PropTypes.oneOfType([  // required number or array of numbers
        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],                   // acceptable values
            ['', {}, [], Symbol(), true] // unacceptable values
        ];
        testPropTypes(MyComponent, 'myProp1', testValues, {myProp2: 123});
    });

    it('should require a number or an array of numbers for myProp2', () => {
        const testValues = [
            [0, [0]],                          // acceptable values
            ['', {}, [], Symbol(), true, null] // unacceptable values
        ];
        testPropTypes(MyComponent, 'myProp2', testValues);
    });
});

该代码在简单情况下似乎可以正常工作。但是,对于更复杂的测试道具值propType(即for),其子数组不可接受myProp2,会产生一些有趣的结果。是否存在null(测试道具是可选的还是必需的)都没有区别,即,它始终保持正确的行为。但是,其他测试道具类型值似乎以某种神秘的方式相互影响。如果使用单个null不可接受的测试道具值,则测试将按预期执行。但是,如果使用了多个这样的null不可接受的测试属性值,则测试将中断,并做出响应,就好像第二,第三等不可接受的类型(同样是,而不是null)是可以接受的。

发生了什么事,我该如何解决?


问题答案:

简短答案

简短的答案是,对于至少某些复杂的propTypesfor
myProp2,您只能包括null任何类型的单个非测试道具类型。这是此方法的固有局限性,它来自React /
Jest的内置特性,该特性会导致多个错误情况,否则可能会产生相同的错误消息,因此仅报告一次。实际上,即使对于propTypes诸如for这样的简单对象myProp1,也存在一个相关但略微隐藏的限制:您可以包括任意数量的不同的不可接受的非null测试属性值,但不能包含多个
相同类型的值 。例如,['', {}, []]将工作,但['', 'x', {}, []]不会(注意,有两个字符串)。


这个限制很重要,因为目前似乎还没有更好的方法来测试propTypesReact。但是,此方法所propTypes施加的约束似乎是可管理的,因此仍可以进行合理测试。

细节

当前,如何使用这种方法(即console.error模拟)存在一些重大限制,如果步调过度,则可能是一些难以跟踪的测试错误的源头。

这些限制的根源是React的行为(或者响应Jest的Jest?),该行为内置于其错误报告机制中。目前,它似乎只会产生多个console.error消息,至少对于propTypes问题,当这些消息彼此不同时。推测其背后的原因是重复的相同消息不会提供新信息,因此此类消息应仅在第一次显示,这似乎是合理的。但是,这意味着两个不同的错误条件,当它们分别发生时,会产生相同的错误消息,而当它们在同一测试运行中出现时,只会产生一条错误消息。所有后续的相同消息均被禁止。这对诸如此类的策略有进一步的影响,这些策略必然期望其输出console.error与测试失败条件完全相关,如下所示。

当前,为简单起见propTypesmyProp1例如示例代码中的情况),对于不同数据类型的所有不可接受的prop值,似乎会出现不同的错误消息,例如

"Warning: Failed prop type: Invalid prop 'myProp1' of type 'string'
supplied to 'MyComponent', expected 'number'."

但是, 相同类型 的第二个测试prop值 错误消息似乎抑制了其预期的错误消息。因此,所有不同数据类型(例如)的不可接受值的数组[123, [123], '123']将导致每个值产生预期的错误消息,从而使测试正常进行。然而,在其中的一些具有相同的数据类型不可接受的值,例如阵列[123, 456, [123], '123'],将
工作,因为只有任何特定的数据类型将产生预期的错误消息的所述第一值,并且因此对于同样的任何后续的推定错误消息类型的值将被抑制,从而破坏测试。因此,为简单propTypes起见
,只要它们都是不同的数据类型 ,就可以使用任意数量的不可接受的测试属性值 __。
这似乎不是一个大问题,因为无论如何您都不需要测试特定数据类型的多个值,但是您需要意识到这一警告。

然而,也许更重要的是,一些复杂的propTypes(如for myProp2)自相矛盾(尽管可能合理)会导致更加简化的错误消息,例如

"Warning: Failed prop type: Invalid prop 'myProp2' supplied to 'MyComponent'."

但是,这意味着,只有 任何数据类型 的第一个null不可接受的测试属性值 都会 生成错误消息,而使用其他不可接受的值进行的 所有
后续测试均会抑制其错误消息。因此,不幸的是,对于如此复杂的测试,您 只能 为测试套件中特定组件的特定道具包含 一个
不可接受的道具值。这不包括必需的Complex 的或值,因为这些值会产生不同的错误消息,因此不会被抑制。请注意,但是,您仍然 可以 测试尽可能多的
可接受值 propTypes null``undefined``propType
__所需的值,例如,允许您myProp2在示例代码中测试多个可能的可接受的prop值。更令人困惑的是,这种限制不仅在测试内, 而且在测试之间也存在
。因此,对于特定组件的任何特定道具,任何测试套件只能包含一个不可接受的道具类型测试。这似乎是一个重大限制,并且牢记这一点是绝对必要的。但是,实际上可能并没有最初听起来那样的局限性,因为通常不会期望多次针对特定组件测试特定道具的不可接受值。因此,这种方法(即嘲笑console.error)似乎仍然是合理的,并且propTypes无论如何仍然是唯一真正的测试方法。

请注意,此限制将来可能会更改,只要React和/或Jest console.error响应不适当的prop值而更改其使用方式。

另请注意,我还没有确切的反应如何调查/玩笑执行错误报告的其他复杂的propTypes,例如React.PropTypes.arrayOf... .objectOf... .shape等推测,稳健地测试这些你首先需要研究什么样的错误消息不适当的值,以及生产如果有此类消息被禁止显示,



 类似资料:
  • 我试图为我的类“Sinus”(用于计算浮点的Sinus)运行一个测试,但当我试图运行这个测试来生成我的Cobertura覆盖率报告时,它不起作用,我真的不知道为什么!你有什么建议或解释吗?(我使用cmd:mvn cobertura:cobertura) -这是我的测试: 结果是: 那有什么问题?有什么想法吗?这是我的pom。xml如下:

  • 我最近开始使用QUnit来单元测试我的JavaScript,我有点困惑的功能在那里留档:。 根据文档,设计用于: [s]指定在测试中预期运行多少个断言。 这是他们给出的例子: 我在这里唯一看到的是维护噩梦。每次向测试添加断言时,都必须更新该数字,否则测试将失败。这种功能是否有实际应用?

  • 每当我运行它时,它只会显示图像应该位于的空间下的按钮,但即使图像空间在那里,也没有图像。 这是关于intelliJ的,我尝试了很多解决方案,但都不起作用。 代码的第一部分 代码的第二部分 文件夹

  • 我有一个带有的spring boot应用程序。 我还使用并在其中扩展。 当我尝试@AutoWired我拥有的服务时: 原因:org.springframework.beans.factory.noSuchBeanDefinitionException:没有“com.api.core.service.countryService”类型的合格bean可用:应至少有一个合格的自动候选bean。依赖项注释

  • 我有一个项目,其中< code>repository及其测试- 位于不同的模块中。我喜欢这样组织我的项目。问题是,当我试图运行测试时,Spring说没有这样的bean。下面是详细的错误消息。我不明白黑魔法泉在这里做什么,为什么它会耗尽法力。 [错误] 应返回所有经过的时间: 0.009 秒 到目前为止我所尝试的: 将测试类和存储库类放在同一个包中(但是,它们放在目录结构中的位置。测试转到,而存储库

  • 似乎每个类只能用Jsoup创建一个get请求,因为当我将替换为时,我放入中的一个会编译,而另一个会出错。 下面是我的代码和错误: 错误: javax.net.ssl.sslhandShakeException:收到致命警报:在java.base/sun.security.ssl.alert.createsslException(alert.java:128)在java.base/sun.secur