反应测试中的间谍功能未触发
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 测试库还很陌生,但我注意到了一些事情:
- 在您的测试中,您将一个间谍作为道具
handleChange
的值传递给您的组件,它没有;正如您所说:“不接受任何道具”。
- 您的组件 定义了
handleChange
您使用事件处理程序的函数,它不是从道具中获取的。
- 您的
handleChange
函数应该仅作为 prop 传递给输入元素,而不是 div。
- 每个输入应该有一个处理程序,而不是为所有输入调用同一个处理程序。
就是说,为了让您的测试提供任何值,您应该更改 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.
我有一个受控组件,其表单由两个单选按钮和一个文本输入组成。我有一个为文本输入的 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 测试库还很陌生,但我注意到了一些事情:
- 在您的测试中,您将一个间谍作为道具
handleChange
的值传递给您的组件,它没有;正如您所说:“不接受任何道具”。 - 您的组件 定义了
handleChange
您使用事件处理程序的函数,它不是从道具中获取的。 - 您的
handleChange
函数应该仅作为 prop 传递给输入元素,而不是 div。 - 每个输入应该有一个处理程序,而不是为所有输入调用同一个处理程序。
就是说,为了让您的测试提供任何值,您应该更改 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.