在测试 React 组件 onClick 时监视功能检查

Spying on function checking when testing React component onClick

我有一个父组件和一个子组件。

父组件:

const ParentComponent = () => {

    const click_button = (role) => {
        document.getElementById(role).innerHTML = role;
    }

    return (
        <div>
            <ChildButton id= 'button_child' name='button_1' onClick={() => {
                click_button('role_1')
            }}/>
            <div>
                <p id="role_1"/>
                <p id="role_2"/>
                <p id="role_3"/>
            </div>
        </div>

    )

}

export default ParentComponent;

子组件

import React from 'react';

const ChildButton = (props) => {

    return (
        <React.Fragment>
            <button onClick={props.onClick}>{props.name}</button>
        </React.Fragment>
    )
}

export default ChildButton;

ParentComponent的测试之一:

    it('buttons should render correctly', () => {
        const wrapper shallow(<ParentComponent/>);
        const instance = wrapper.instance();
        jest.spyOn(instance, 'click_button');
        expect(instance.click_button).toHaveBeenCalledTimes(0);
        wrapper.find('#button_child').simulate('click');
        expect(instance.click_button).toHaveBeenCalledTimes(1);
    });

我的应用程序使用 jest 和 enzyme 进行测试。示例中的点击功能需要在 ParentComponent 中进行测试。但是,当我尝试访问该按钮时,测试失败了,这是因为该按钮位于 childButton 组件中。

所以基本上问题是如何测试 ParentComponent 中的 click_button 函数?

上面的例子实例是空的,酶文档说会是这种情况。现在我看到个人绕过这个的唯一方法是 'watching' 控制台日志,这对我来说似乎有点 hacky?

我正在努力坚持使用 Enzyme 和 Jest,因为这是我编写单元测试的内容,我希望我的集成测试可以效仿。

感谢您的帮助。

测试组件的行为而不是实现细节。使用 enzymemount() 函数一起测试父子组件。 React 功能组件没有实例,但 class 个组件有实例。

例如

parent.jsx:

import ChildButton from './child';

const ParentComponent = () => {
  const click_button = (role) => {
    document.getElementById(role).innerHTML = role;
  };

  return (
    <div>
      <ChildButton
        id="button_child"
        name="button_1"
        onClick={() => {
          click_button('role_1');
        }}
      />
      <div>
        <p id="role_1" />
        <p id="role_2" />
        <p id="role_3" />
      </div>
    </div>
  );
};

export default ParentComponent;

child.jsx:

import React from 'react';

const ChildButton = (props) => {
  return (
    <React.Fragment>
      <button onClick={props.onClick}>{props.name}</button>
    </React.Fragment>
  );
};

export default ChildButton;

parent.test.jsx:

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

describe('66698493', () => {
  beforeAll(() => {
    const div = document.createElement('div');
    div.setAttribute('id', 'container');
    document.body.appendChild(div);
  });
  it('should change the inner HTML', () => {
    const wrapper = mount(<ParentComponent />, { attachTo: document.getElementById('container') });
    expect(document.getElementById('role_1').innerHTML).toEqual('');
    wrapper.find('button').simulate('click');
    expect(document.getElementById('role_1').innerHTML).toEqual('role_1');
  });
});

测试结果:

 PASS  examples/66698493/parent.test.jsx
  66698493
    ✓ should change the inner HTML (46 ms)

------------|---------|----------|---------|---------|-------------------
File        | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
------------|---------|----------|---------|---------|-------------------
All files   |     100 |      100 |     100 |     100 |                   
 child.jsx  |     100 |      100 |     100 |     100 |                   
 parent.jsx |     100 |      100 |     100 |     100 |                   
------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        6.067 s

jest.config.js:

module.exports = {
  preset: 'ts-jest/presets/js-with-ts',
  testEnvironment: 'enzyme',
  setupFilesAfterEnv: [
    'jest-enzyme',
  ],
  setupFiles: ['./jest.setup.js'],
  testEnvironmentOptions: {
    enzymeAdapter: 'react16',
  },
};