酶/ Jest 间谍在onClick事件中未被调用

3
我想使用Enzyme / Jest测试React组件的事件处理程序,但是我的spy函数从未被调用...。
我的组件有一个带有id的div,我正在使用它来查找dom元素。
 render() {
    return (
        <div>
            <Top
                {...this.props}
            />
            <div 
                id = 'keyboard_clickable'
                onClick = {this._handleClick}
                style= {styles.main}>
                {this._showKeyBoard()}
            </div>
            <input onChange = {() => {}}/>
      </div>
    );
  }
}

我的测试

describe('onclick function is called ...', () => {
  it.only('spyOn', () => {
    const spy = jest.fn()

    const wrapper = shallow(
      <Keyboard 
      _getData      = { () => {} }
      _erase        = { () => {} }
      _get_letters  = { () => {} }
      _createWord   = { () => {} }
      _modeSwitch   = { () => {} }
      onClick       = { spy      }
      />
    )

    wrapper.find('#keyboard_clickable').simulate('click', {
      target:{
        parentElement:{ id: 5 },
        id:6
        }
    })
    expect(spy).toHaveBeenCalled();

  })
})

my HandleClick

_handleClick = e => {
    let parent = e.target.parentElement;
    if(e.target.id || (!isNaN(parent.id) && parent.id > 0) ) {
        this.props._getData(e.target.id || e.target.parentElement.id)
        this.setState({status:'ok'})
    }else{
        this.setState({status:'Use numbers between 2 and 9'},()=>{
            return alert(this.state.status)
        })

    }
}

测试输出

Expected mock function to have been called, but it was not called.

请问您能展示一下Keyboard._handleClick函数的内容吗?我怀疑它可能没有调用Keyboard.props.onClick。 - Jemi Salo
是的,它没有调用Keyboard.props._handleClick方法,而是调用了Keyboard._handleClick方法。 - Nilos
请将其添加到您的原始帖子中,这里几乎无法阅读。 - Axnyff
您的 _handleClick 方法从未调用 onClick props。相反,您可以测试状态是否正确更改以及是否调用了 _getData props。 - Axnyff
2个回答

3

为了测试事件处理程序是否被调用,您需要将事件处理程序替换为一个模拟函数。一种方法是扩展组件类:

class TestKeyboard extends Keyboard {
  constructor(props) {
    super(props)
    this._handleClick = this.props._handleClick
  }
}

describe('onclick function is called ...', () => {
  it.only('spyOn', () => {
    const spy = jest.fn()

    const wrapper = shallow(
      <TestKeyboard 
      _getData      = { () => {} }
      _erase        = { () => {} }
      _get_letters  = { () => {} }
      _createWord   = { () => {} }
      _modeSwitch   = { () => {} }
      _handleClick  = { spy      }
      />
    )

    wrapper.find('#keyboard_clickable').simulate('click', {
      target:{
        parentElement:{ id: 5 },
        id:6
        }
    })
    expect(spy).toHaveBeenCalled();

  })
})

属性_handleClick替换了Keyboard._handleClick,并且在点击元素触发onClick时被调用。

或者,使用jest.spyOn

如果您需要让事件处理程序执行测试它被调用的内容,可以使用jest.spyOn。我认为这种方法更加复杂,但更加灵活。

import { mount } from 'enzyme'

describe('onclick function is called ...', () => {
  it.only('spyOn', () => {
    const wrapper = mount(
      <Keyboard 
      _getData      = { () => {} }
      _erase        = { () => {} }
      _get_letters  = { () => {} }
      _createWord   = { () => {} }
      _modeSwitch   = { () => {} }
      />
    )

    const spy = jest.spyOn(wrapper.instance(), '_handleClick')
    wrapper.instance().forceUpdate()

    wrapper.find('#keyboard_clickable').simulate('click', {
      target:{
        parentElement:{ id: 5 },
        id:6
        }
    })
    expect(spy).toHaveBeenCalled();

  })
})

请注意,当使用浅层渲染时,这将失败,因此您必须使用enzyme.mount代替。

谢谢,确实通过了测试! - Nilos
我缺少了wrapper.instance().forceUpdate(),谢谢。 - Tonio

1
似乎在浅渲染中使用enzyme模拟点击确实可以正常工作,但仅当我强制更新时才有效,就像Jemi的解决方案中那样。
例如:
 beforeEach(() => {
    wrapper = shallow(<VehicleDamage handleSubmit={mockFunction} onPrevClick={mockFunction} />);
});

it('handlePrevClick is called on click', function() {
    const spyHandlePrevClick = jest.spyOn(wrapper.instance(), 'handlePrevClick');
    wrapper.instance().forceUpdate(); // I assume required to assign mocked function

    let buttonContainer = wrapper.find('ButtonContainer').dive();
    let button = buttonContainer.find('Button').at(0);

    button.simulate('click', {
        preventDefault: () => jest.fn()
    });

    expect(spyHandlePrevClick).toHaveBeenCalled();
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接