Jest.js “setProps()”未触发笑话中的“useEffect”

aiqt4smr  于 2023-03-21  发布在  Jest
关注(0)|答案(3)|浏览(167)

当我在测试用例中更新功能组件的属性时,它没有触发useEffect,但是它更新了myComp中的属性。

组件示例:

const myComp = ({userId, myAction}) => {
 useEffect(() => {
  myAction(userId);
 }, [userId]);

  return <div>Test</div>
}

测试用例示例:

.....
describe('Testing MyComp', () => {
  it('should call myAction with userID', () => {
    const userId = 'testId';
    wrapper.setProps({userId});
    expect(myAction).toHaveBeenCalledWith(userId);
  });  
});
yduiuuwa

yduiuuwa1#

在React浅渲染器中不调用useEffect()useLayoutEffect()。请参见useEffect not called when the component is shallow rendereredthis issue
您应该使用mount函数。
例如
index.tsx

import React, { useEffect } from 'react';

export const MyComp = ({ userId, myAction }) => {
  useEffect(() => {
    myAction(userId);
  }, [userId]);

  return <div>Test</div>;
};

index.test.tsx

import React from 'react';
import { mount } from 'enzyme';
import { MyComp } from './';

describe('67312763', () => {
  it('should pass', () => {
    const props = {
      userId: '1',
      myAction: jest.fn(),
    };
    const wrapper = mount(<MyComp {...props} />);
    expect(props.myAction).toHaveBeenCalledWith('1');
    const userId = '2';
    wrapper.setProps({ userId });
    expect(props.myAction).toHaveBeenCalledWith('2');
  });
});

测试结果:

PASS  examples/67312763/index.test.tsx (7.221 s)
  67312763
    ✓ should pass (31 ms)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |     100 |      100 |     100 |     100 |                   
 index.tsx |     100 |      100 |     100 |     100 |                   
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        7.731 s

软件包版本:

"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.5",
"jest": "^26.6.3",
"jest-enzyme": "^7.1.2",
"react": "^16.14.0",
8aqjt8rx

8aqjt8rx2#

@slideshowp2上面的答案是正确的,但是如果你像我一样发现setProps即使在你使用mount的时候仍然不工作,这可能是对你有用的信息。
React可能会将多个setState()调用的状态更新批量处理成一个更新(看看这个),这 * 可能 * 是异步的,因此expect get被触发,但setState还没有运行(因为它在JS事件循环中等待运行),您的测试失败。
您可能会问,如何避免这种情况?将您的expect封装在setTimeout中,以便它在相同的异步位置结束,并将在setState之后运行!
大概是这样的

describe('Testing MyComp', () => {
  it('should call myAction with userID', () => {
    const userId = 'testId';
    wrapper.setProps({userId});
    setTimeout(() => {
      expect(myAction).toHaveBeenCalledWith(userId);
    }, 0)
  });  
});

另外,请注意,我不喜欢这个,但它确实有效。

csbfibhn

csbfibhn3#

要触发任何钩子,您需要使用这个包-https://github.com/mikeborozdin/jest-react-hooks-shallow
那么在你的测试中

import {act} from 'react-dom/test-utils'

describe('Testing MyComp', () => {
  it('should call myAction with userID', () => {
    const userId = 'testId';

    // if you follow the jest setup in the 
    // jest-react-hooks-shallow you get withHooks
    // enabled in all your tests
    withHooks(()=> {
        act(()=>
            wrapper.setProps({userId})
        );
    });
    wrapper.update();

    expect(myAction).toHaveBeenCalledWith(userId);
  });  
});

相关问题