单元测试 React 功能组件的功能

Posted

技术标签:

【中文标题】单元测试 React 功能组件的功能【英文标题】:Unit test React functional component's function 【发布时间】:2021-08-18 19:48:48 【问题描述】:

无论如何我们可以在反应功能组件中对功能进行单元测试。由于wrapper.instance() 将为功能组件返回 null,因此在测试中包含此功能以获得最大覆盖率的最佳方法是什么。


const SimpleFC: React.FC = () => 

    const callbackFunction = () => 
        // Do Stuffs
    

    return (
        <ChildComponent callback=callbackFunction />
    )


export  SimpleFC ;

在这段代码中我们如何调用callbackFunction

提前致谢

【问题讨论】:

恕我直言,测试不应专注于实现细节。断言一个函数是否被调用不会增加任何值。相反,您应该做的是测试调用 xyz 函数时 UI 的变化情况。是否将某些内容添加到 UI 或从 UI 中删除。您的测试应该更多地关注用户将如何使用您的应用程序。用户不关心你的 callbackFunction 是否被调用。他只关心他在 UI 中看到的内容。 回调实现的行为是什么? ChildComponent 将如何触发它? @Shyam 是的,用户关心的是 UI 更改,但要更改 UI,我们需要触发该功能。我的问题是如何在不与子组件交互的情况下调用函数。 【参考方案1】:

通过您使用wrapper.instance() API,我武断地认为您使用的是enzyme 库。您可以使用.invoke(invokePropName)(...args) => Any 方法直接调用ChildComponent 上的函数道具。

例如

SimpleFC.tsx:

import React from 'react';
import ChildComponent from './ChildComponent';

const SimpleFC: React.FC = () => 
  const callbackFunction = () => 
    // Do Stuffs
    console.log('Do Stuffs');
  ;

  return <ChildComponent callback=callbackFunction />;
;

export  SimpleFC ;

ChildComponent.tsx:

import React from 'react';

export default function ChildComponent( callback ) 
  return <div onClick=callback>child component</div>;

SimpleFC.test.tsx:

import  shallow  from 'enzyme';
import React from 'react';
import  SimpleFC  from './SimpleFC';

describe('67774847', () => 
  it('should pass', () => 
    const logSpy = jest.spyOn(console, 'log');
    const wrapper = shallow(<SimpleFC />);
    wrapper.invoke('callback')();
    expect(logSpy).toBeCalledWith('Do Stuffs');
    logSpy.mockRestore();
  );
);

测试结果:

 PASS  examples/67774847/SimpleFC.test.tsx (8.752 s)
  67774847
    ✓ should pass (48 ms)

  console.log
    Do Stuffs

      at console.<anonymous> (node_modules/jest-environment-enzyme/node_modules/jest-mock/build/index.js:866:25)

--------------------|---------|----------|---------|---------|-------------------
File                | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
--------------------|---------|----------|---------|---------|-------------------
All files           |      90 |      100 |   66.67 |      90 |                   
 ChildComponent.tsx |   66.67 |      100 |       0 |   66.67 | 4                 
 SimpleFC.tsx       |     100 |      100 |     100 |     100 |                   
--------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        9.654 s

【讨论】:

我试过invoke 这样wrapper.invoke('getCustomerAddress')() 我收到一个错误“这个表达式不可调用。类型'never'没有调用签名.ts(2349)类型'string'的参数不能分配给“从不”类型的参数。” @sinthu225 是 TS 类型问题,你可以 typecast 到any。根据您的问题,我无法重现此问题。您的问题中没有 getCustomerAddress 函数属性。 我禁用了 linting 并像 any 一样强制转换。 TypeError: ShallowWrapper::invoke() 需要一个 prop 的名称,其值为一个函数 const wrapper = shallow(&lt;Foo /&gt;); wrapper.find('button').invoke('onClick')().then(() =&gt; // expect() ); 如果我们有按钮或任何东西,这将起作用

以上是关于单元测试 React 功能组件的功能的主要内容,如果未能解决你的问题,请参考以下文章

React组件单元测试

使用 react-navigation 中的 useRoute 进行 Jest 单元测试

Angular - 组件中订阅功能的单元测试

React Native Jest - 如何使用多个钩子测试功能组件?无法存根 AccessiblityInfo 模块

reactjs中组件的单元测试功能使用业力和茉莉花

直接在功能组件中测试功能