Jest 预期模拟函数已被调用,但未被调用 [英] Jest Expected mock function to have been called, but it was not called

查看:23
本文介绍了Jest 预期模拟函数已被调用,但未被调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我查看了解决测试类属性但没有成功的各种建议,并想知道是否有人可以对我可能出错的地方有更多的了解,这里是我尝试过的所有测试错误预期已调用模拟函数,但未调用.

Search.jsx

import React, { Component } from 'react'从道具类型"导入 { func }从'./Input'导入输入从'./Button'导入按钮类 SearchForm 扩展组件 {静态 propTypes = {切换警报:func.isRequired}构造函数(){极好的()this.state = {搜索词: ''}this.handleSubmit = this.handleSubmit.bind(this)}handleSubmit = () =>{const { searchTerm } = this.stateconst { toggleAlert } = this.propsif (searchTerm === 'mocky') {切换警报({警报类型:'成功',alertMessage: '成功!!!'})this.setState({搜索词: ''})} 别的 {切换警报({警报类型:'错误',alertMessage: '错误!!!'})}}handleChange = ({ target: { value } }) =>{this.setState({搜索词:值})}使成为() {const { searchTerm } = this.stateconst btnDisabled = (searchTerm.length === 0) === true返回 (<div className="井搜索-表单软推--底部"><ul className="form-fields list-inline"><li className="flush"><输入id="搜索"名称=搜索"类型=文本"placeholder="输入搜索词..."类名=文本输入"值={searchTerm}onChange={this.handleChange}/><div className="feedback push-half--right"/><li className="push-half--left"><Button className="btn btn--positive" disabled={btnDisabled} onClick={this.handleSubmit}>搜索</按钮>

)}}导出默认 SearchForm

第一个选项:

it('提交时应该调用handleSubmit函数', () => {const wrapper = Shallow(<Search toggleAlert={jest.fn()}/>)const spy = jest.spyOn(wrapper.instance(), 'handleSubmit')wrapper.instance().forceUpdate()wrapper.find('.btn').simulate('click')期望(间谍).toHaveBeenCalled()spy.mockClear()})

第二个选项:

it('提交时应该调用handleSubmit函数', () => {const wrapper = Shallow(<Search toggleAlert={jest.fn()}/>)wrapper.instance().handleSubmit = jest.fn()包装器.更新()wrapper.find('.btn').simulate('click')期望(wrapper.instance().handleSubmit).toHaveBeenCalled()})

我知道有一个类属性,该函数是类的一个实例,需要更新组件以注册该函数,但是看起来像组件 handleSubmit 函数被调用而不是模拟?

将 handleSubmit 交换为类函数作为方法使我可以访问类原型,该类原型在监视 Search.prototype 时通过了测试,但我真的很想获得类属性方法的解决方案.

所有的建议和建议将不胜感激!

解决方案

我认为单元测试应该足够健壮以捕获错误,如果任何不受欢迎的代码发生变化.

请在测试中包含严格的断言.

对于条件语句,也请覆盖分支.例如,在 ifelse 语句的情况下,您将不得不编写 两个 测试.

对于用户操作,您应该尝试模拟操作而不是手动调用函数.

请看下面的例子,

从'react'导入React;从酶"导入{浅};从组件/搜索"导入 { SearchForm };描述('搜索组件',()=> {让包装;const toggleAlert = jest.fn();const handleChange = jest.fn();常量成功警报 = {警报类型:'成功',alertMessage: '成功!!!'}常量错误警报 = {警报类型:'错误',alertMessage: '错误!!!'}beforeEach(() => {包装器 = 浅(<SearchForm toggleAlert={toggleAlert}/>);});it('"handleSubmit" 被 "mocky" 调用', () => {期望(toggleAlert).not.toHaveBeenCalled();期望(handleChange).not.toHaveBeenCalled();wrapper.find('Input').simulate('change', { target: { value: 'mocky' } });期望(handleChange).toHaveBeenCalledTimes(1);期望(wrapper.state().searchTerm).toBe('mocky');wrapper.find('Button').simulate('click');期望(toggleAlert).toHaveBeenCalledTimes(1);期望(toggleAlert).toHaveBeenCalledWith(successAlert);期望(wrapper.state().searchTerm).toBe('');});it('"handleSubmit" 被称为 "other than mocky"', () => {期望(toggleAlert).not.toHaveBeenCalled();期望(handleChange).not.toHaveBeenCalled();wrapper.find('Input').simulate('change', { target: { value: 'Hello' } });期望(handleChange).toHaveBeenCalledTimes(1);期望(wrapper.state().searchTerm).toBe('Hello');wrapper.find('Button').simulate('click');期望(toggleAlert).toHaveBeenCalledTimes(1);期望(toggleAlert).toHaveBeenCalledWith(errorAlert);期望(wrapper.state().searchTerm).toBe('Hello');});});

I've looked at various suggestions to solve testing a class property with no success and was wondering if anyone could possibly cast a little more light on where I may be going wrong, here are the tests I've tried all with the error Expected mock function to have been called, but it was not called.

Search.jsx

import React, { Component } from 'react'
import { func } from 'prop-types'
import Input from './Input'
import Button from './Button'

class SearchForm extends Component {
  static propTypes = {
    toggleAlert: func.isRequired
  }

  constructor() {
    super()

    this.state = {
      searchTerm: ''
    }

    this.handleSubmit = this.handleSubmit.bind(this)
  }

  handleSubmit = () => {
    const { searchTerm } = this.state
    const { toggleAlert } = this.props

    if (searchTerm === 'mocky') {
      toggleAlert({
        alertType: 'success',
        alertMessage: 'Success!!!'
      })

      this.setState({
        searchTerm: ''
      })
    } else {
      toggleAlert({
        alertType: 'error',
        alertMessage: 'Error!!!'
      })
    }
  }

  handleChange = ({ target: { value } }) => {
    this.setState({
      searchTerm: value
    })
  }

  render() {
    const { searchTerm } = this.state
    const btnDisabled = (searchTerm.length === 0) === true

    return (
      <div className="well search-form soft push--bottom">
        <ul className="form-fields list-inline">
          <li className="flush">
            <Input
              id="search"
              name="search"
              type="text"
              placeholder="Enter a search term..."
              className="text-input"
              value={searchTerm}
              onChange={this.handleChange}
            />
            <div className="feedback push-half--right" />
          </li>
          <li className="push-half--left">
            <Button className="btn btn--positive" disabled={btnDisabled} onClick={this.handleSubmit}>
              Search
            </Button>
          </li>
        </ul>
      </div>
    )
  }
}

export default SearchForm

First option:

it('should call handleSubmit function on submit', () => {
    const wrapper = shallow(<Search toggleAlert={jest.fn()} />)
    const spy = jest.spyOn(wrapper.instance(), 'handleSubmit')
    wrapper.instance().forceUpdate()
    wrapper.find('.btn').simulate('click')
    expect(spy).toHaveBeenCalled()
    spy.mockClear()
  })

Second option:

it('should call handleSubmit function on submit', () => {
    const wrapper = shallow(<Search toggleAlert={jest.fn()} />)
    wrapper.instance().handleSubmit = jest.fn()
    wrapper.update()
    wrapper.find('.btn').simulate('click')
    expect(wrapper.instance().handleSubmit).toHaveBeenCalled()
  })

I get that with a class property the function is an instance of the class requiring the component to be updated in order to register the function, it looks however like the component handleSubmit function gets called instead of the mock?

Swapping out handleSubmit to be a class function as a method gives me access on the class prototype which passes the test when spying on Search.prototype but I'd really like to get a solution to the class property approach.

All suggestions and recommendations would be grateful!

解决方案

I suppose the unit test should be robust enough to catch the error, if case of any undesirable code changes.

Please include strict assertions in your tests.

For the conditional statements, please cover the branches as well. E.g in case of if and else statement you will have to write two tests.

For user actions, you should try to simulate the actions rather than calling the function manually.

Please see the example below,

import React from 'react';
import { shallow } from 'enzyme';
import { SearchForm } from 'components/Search';


describe('Search Component', () => {
  let wrapper;
  const toggleAlert = jest.fn();
  const handleChange = jest.fn();
  const successAlert = {
    alertType: 'success',
    alertMessage: 'Success!!!'
  }
  const errorAlert = {
    alertType: 'error',
    alertMessage: 'Error!!!'
  }
  beforeEach(() => {
    wrapper = shallow(<SearchForm toggleAlert={toggleAlert} />);
  });
  it('"handleSubmit" to have been called with "mocky"', () => {
    expect(toggleAlert).not.toHaveBeenCalled();
    expect(handleChange).not.toHaveBeenCalled();
    wrapper.find('Input').simulate('change', { target: { value: 'mocky' } });
    expect(handleChange).toHaveBeenCalledTimes(1);
    expect(wrapper.state().searchTerm).toBe('mocky');
    wrapper.find('Button').simulate('click');
    expect(toggleAlert).toHaveBeenCalledTimes(1);
    expect(toggleAlert).toHaveBeenCalledWith(successAlert);
    expect(wrapper.state().searchTerm).toBe('');
  });

  it('"handleSubmit" to have been called with "other than mocky"', () => {
    expect(toggleAlert).not.toHaveBeenCalled();
    expect(handleChange).not.toHaveBeenCalled();
    wrapper.find('Input').simulate('change', { target: { value: 'Hello' } });
    expect(handleChange).toHaveBeenCalledTimes(1);
    expect(wrapper.state().searchTerm).toBe('Hello');
    wrapper.find('Button').simulate('click');
    expect(toggleAlert).toHaveBeenCalledTimes(1);
    expect(toggleAlert).toHaveBeenCalledWith(errorAlert);
    expect(wrapper.state().searchTerm).toBe('Hello');
  });
});

这篇关于Jest 预期模拟函数已被调用,但未被调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆