【问题标题】:Enzyme/Jest Class method spy not being called on input change输入更改时未调用酶/玩笑类方法间谍
【发布时间】:2022-01-11 11:40:11
【问题描述】:

起初,我认为我的代码的其他方面有问题。所以我在一个新创建的项目中创建了一个新的简化版本的组件并为它编写了测试,但我的 spy 仍然没有被调用。

这是我正在测试的组件:

import React from 'react';

class TextEditor extends React.Component {
  handleChange = (e) => {
    console.log({ value: e.target.value });
  }

  render() {
    return (
      <div>
        <input type="text" name="name" id="name" onChange={this.handleChange} />
      </div>
    );
  }
}

export default TextEditor;

这是单元测试:

import React from 'react';
import { shallow } from 'enzyme';
import TextEditor from '../TextEditor';

describe('TextEditor', () => {
  it('handles change event', () => {
    const wrapper = shallow(<TextEditor />);
    const spy = jest.spyOn(wrapper.instance(), 'handleChange');
    wrapper.find('input').simulate('change', { target: { value: 'test value' }});
    expect(spy).toHaveBeenCalledTimes(1);
  });
});

运行测试的结果:

当我运行它时,它失败了,因为没有调用间谍。但请注意,handleChange 函数中的 console.log 语句被执行。因此测试实际上调用了该函数,但未识别出 spy 已被调用。

我可能做错了什么?感谢您的想法。

【问题讨论】:

  • handleChange 不是实例的属性,它是嵌套在另一个函数中的函数。从外面是无法进入的。即使它可访问的,你的测试也将是实现细节。改为测试 行为 - 是否记录了正确的值?
  • 嗨@jonrsharpe,感谢您的评论。我认为您的评论是基于假设被测试的组件是功能组件但它实际上是一个类组件,因此方法 does 属于实例;还是我误会了你?
  • 你是对的,它是;对不起,我看错了。不过,重点是:测试行为而不是实现。

标签: reactjs unit-testing jestjs enzyme


【解决方案1】:

handleChange 方法是类属性,不是类的实例方法。

如果你坚持使用类属性,你应该在窥探后调用wrapper.instance().forceUpdate()。见issue#365

例如

TextEditor.tsx:

import React from 'react';

class TextEditor extends React.Component {
  handleChange = (e) => {
    console.log({ value: e.target.value });
  };

  render() {
    return (
      <div>
        <input type="text" name="name" id="name" onChange={this.handleChange} />
      </div>
    );
  }
}

export default TextEditor;

TextEditor.test.tsx:

import { shallow } from 'enzyme';
import React from 'react';
import TextEditor from './TextEditor';

describe('TextEditor', () => {
  it('handles change event', () => {
    const wrapper = shallow(<TextEditor />);
    const spy = jest.spyOn(wrapper.instance(), 'handleChange');
    wrapper.instance().forceUpdate();
    wrapper.find('input').simulate('change', { target: { value: 'test value' } });
    expect(spy).toHaveBeenCalledTimes(1);
  });
});

测试结果:

 PASS  examples/70652888/TextEditor.test.tsx (13.006 s)
  TextEditor
    ✓ handles change event (100 ms)

  console.log
    { value: 'test value' }

      at TextEditor.handleChange (examples/70652888/TextEditor.tsx:5:13)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        14.708 s

另外,请参阅answer

【讨论】:

    猜你喜欢
    • 2019-01-12
    • 1970-01-01
    • 2019-09-13
    • 2021-04-18
    • 1970-01-01
    • 2017-09-26
    • 1970-01-01
    • 2020-09-03
    • 2023-03-27
    相关资源
    最近更新 更多