反应测试中的间谍功能未触发

Spy function in react test is not firing

我有一个受控组件,其表单由两个单选按钮和一个文本输入组成。我有一个为文本输入的 onChange 事件调用的函数,并编写了一个触发更改事件的测试。我希望间谍函数应该被调用一次,但测试总是失败。

测试

test('Update function is called when text entered into searchbox', () => {
    const spy = jest.fn();
    const {getByTestId} = render(<SearchDropdown handleChange={spy}/>);
    expect(getByTestId('searchText').value).toBe("");
    fireEvent.change(getByTestId('searchText'), { target: { value: "23" } });
    expect(getByTestId('searchText').value).toBe("23");
    expect(spy).toHaveBeenCalledTimes(1);
});

组件 - 不接受任何道具

import React, { Component } from 'react'
import { faSearch } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import SearchResults from './SearchResults';

export default class SearchDropdown extends Component {

    constructor(props){
        super(props)

        this.state = {
            type: 'Spec',
            number: '',
        }

    }

    handleChange = (event) => {
        let name = event.target.name;
        let target = event.target.value;
        this.setState({
            [name]: target}
        );
    }

    handleSearch = (event) => {
        event.preventDefault();
        if (this.state.number !== "") {
            console.log("Make request to API");
        }
    }

    render() {
        return (
            <div data-testid="searchMenu">
                <div className="list-group dropdown-menu dropdown-menu-right mr-5 text-center">
                    <h5><FontAwesomeIcon icon={faSearch}/> Quick Search</h5>
                    <form className="m-2">
                        <div className="form-group" onChange={this.handleChange}>
                            <input type="radio" value="Spec" name="type" defaultChecked /> Specification 
                            <input type="radio" value="Claim" name="type" className="ml-2"/> Claim
                        </div>
                        <div className="form-group">
                            <label>Search Number</label>
                            <input type="text" data-testid="searchText" onChange={this.handleChange} value={this.state.number} name="number" className="form-control"/>
                        </div>
                        <SearchResults />
                    </form>
                    <div className="panel panel-default">
                    </div>
                    <button className="bg-transparent border-0 link">Advanced Search</button>
                </div>
            </div>
        )
    }
}

错误信息

expect(jest.fn()).toHaveBeenCalledTimes(1)

    Expected mock function to have been called one time, but it was called zero times.

          fireEvent.change(getByTestId('searchText'), { target: { value: "23" } });
          expect(getByTestId('searchText').value).toBe("23");
          expect(spy).toHaveBeenCalledTimes(1);
                     ^
      });

      test('Clicking search brings up results modal', () => {

      at Object.toHaveBeenCalledTimes (src/Tests/SearchDropdown.test.js:18:17)

我是不是遗漏了什么明显的东西?

我对 React 和 React 测试库还很陌生,但我注意到了一些事情:

  1. 在您的测试中,您将一个间谍作为道具 handleChange 的值传递给您的组件,它没有;正如您所说:“不接受任何道具”。
  2. 您的组件 定义了 handleChange 您使用事件处理程序的函数,它不是从道具中获取的。
  3. 您的 handleChange 函数应该仅作为 prop 传递给输入元素,而不是 div。
  4. 每个输入应该有一个处理程序,而不是为所有输入调用同一个处理程序。

就是说,为了让您的测试提供任何值,您应该更改 SearchDropdown 组件,以便它从父级接收处理程序,或者您测试触发 click/change 输入事件实际上按预期更新了视图。 我认为测试是否调用了内部事件处理函数没有任何价值。 您在测试中使用了 React 测试库,但未按预期方式使用。 来自 React Testing Library Intro:

The utilities this library provides facilitate querying the DOM in the same way the user would. Finding for elements by their label text (just like a user would), finding links and buttons from their text (like a user would). It also exposes a recommended way to find elements by a data-testid as an "escape hatch" for elements where the text content and label do not make sense or is not practical.