reactjs - React - 当父组件将方法作为道具传递时,在哪里对状态变化进行单元测试:父组件还是子组件?
问题描述
我正在尝试找出对以下情况进行单元测试的最佳方法
- 父类组件
App
保存number的状态attendees
以及handleAttendeesChange()
更新状态的方法 App
渲染一个子组件Attendees
并传递给它 2 个 props:currentCount
和onValueChange
问题是:我是否测试App.tsx或Attendees.tsx中的状态是否正确更改?我已经看到了应该测试父组件中的状态更改的示例,但是这些示例表明父组件在 DOM 中而不是在子组件中显示值。
代码如下
应用程序.tsx
import React, { FC, Component } from 'react';
import {Attendees} from './Attendees';
interface AppState {
attendees: number
}
export default class App extends Component<{}, AppState> {
constructor(props:any) {
super(props);
this.handleAttendeesChange = this.handleAttendeesChange.bind(this);
this.state = {
attendees: 0
};
}
handleAttendeesChange(value: number) {
this.setState({ attendees: this.state.attendees + value});
}
render() {
return (
<div>
<h1>Parent Component</h1>
<Attendees currentCount={this.state.attendees} onValueChange={this.handleAttendeesChange} />
</div>
)
}
}
与会者.tsx
import React, { FC } from 'react';
type AttendeesProps = {
currentCount: number,
onValueChange: (value: number) => void
}
export const Attendees:FC<AttendeesProps> = ({ currentCount, onValueChange }) => {
return (
<div>
<button data-testid="countUp" onClick={() => onValueChange(1)}>
Up
</button >
<button data-testid="countDown" onClick={() => onValueChange(-1)}>
Down
</button >
<p data-testid="currentCount">
{currentCount}
</p>
</div>
)
}
这是我目前使用 react-testing-library 在 Attendeees.test.tsx 中测试的内容
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import { unmountComponentAtNode } from "react-dom";
// import { act } from "react-dom/test-utils";
import {Attendees} from './Attendees';
let container: any = null;
beforeEach(() => {
// setup a DOM element as a render target
container = document.createElement("Main");
document.body.appendChild(container);
});
afterEach(() => {
// cleanup on exiting
unmountComponentAtNode(container);
container.remove();
container = null;
});
it("Attendees should respond to callback props", () => {
const onValueChange = jest.fn();
const { getByTestId } = render(<Attendees currentCount={0} onValueChange={onValueChange} />, container)
fireEvent.click(getByTestId('countUp'))
expect(onValueChange).toBeCalledWith(1);
expect(onValueChange).toHaveBeenCalledTimes(1);
expect(getByTestId('currentCount').textContent).toBe('1');
})
解决方案
迟到的答案,但可能会帮助有同样问题的人。
“我是否在 App.tsx 或 Attendees.tsx 中测试状态是否正确更改?”
我们不必测试是否setState
正常工作。但是,如果我们想测试更新的计数是否显示在参加者组件中,我们可以在 中进行测试App.test.tsx
,因为那是状态所在的位置。
结合更多关于测试的想法
我们不必在 中创建容器beforeEach
然后将其删除afterEach
。react-testing-library
照顾它。
这是我的 Attendees.test.tsx 版本:
// Attendees.test.tsx
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import { Attendees } from './Attendees';
describe('Attendees component', () => {
it('should respond to Up button click', () => {
const onValueChange = jest.fn();
render(<Attendees currentCount={0} onValueChange={onValueChange} />);
// Don't have to use data-testid all the time. Here's another way
fireEvent.click(screen.getByText('up', { exact: false }));
expect(onValueChange).toBeCalledWith(1);
expect(onValueChange).toHaveBeenCalledTimes(1);
});
it('should respond to Down button click', () => {
const onValueChange = jest.fn();
render(<Attendees currentCount={0} onValueChange={onValueChange} />);
fireEvent.click(screen.getByText('down', { exact: false }));
expect(onValueChange).toBeCalledWith(-1);
expect(onValueChange).toHaveBeenCalledTimes(1);
});
});
我会将检查当前计数显示的测试放在 App.test.tsx 中:
// App.test.tsx
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import App from './App';
describe('App component', () => {
it('should display increased attendee count when the Up button is clicked', () => {
render(<App />);
// Sometimes it may be a good idea to ensure that the precondition is true
expect(screen.getByLabelText('current-attendee-count').textContent).toBe('0');
fireEvent.click(screen.getByText('up', { exact: false }));
expect(screen.getByLabelText('current-attendee-count').textContent).toBe('1');
});
});
笔记
上面的示例使用 React v17.0.1 和 @testing-library/react v11.2.3 进行了测试。
推荐阅读
- arrays - 使用两个对应的数组遍历命名范围
- android - 垂直回收器内的水平回收器。这种情况的最佳做法是什么?
- python - Github ssh-action 配置在 django 应用程序中部署更改
- haskell - ihp/nix 如何在不编译失败的情况下将 wreq 添加到依赖项?
- javascript - Vue 使用 canvas-datagrid 在控制台显示警告消息
- oracle - ORACLE avg,max,min 工资触发
- mysql - 将 json 数组解组为 struct 数组
- matlab - 我可以用 OOB 误差低的样本重新训练模型吗?
- flutter - Navigator.push 后如何关闭 AlertDialog?
- html - 如何遍历超市网站并获取产品名称和价格?