javascript - How to test class components in react
问题描述
I am trying some unit testing, I created a sandbox with a fake example https://codesandbox.io/s/wizardly-hooks-32w6l (in reality I have a form)
class App extends React.Component {
constructor(props) {
super(props);
this.state = { number: 0 };
}
handleSubmit = (number1, number2) => {
this.setState({ number: this.handleMultiply(number1, number2) })
}
handleMultiply = (number1, number2) => {
return number1 * number2
}
render() {
const { number } = this.state;
return (
<div className="App">
<form onSubmit={e => this.handleSubmit(3, 7)}>
<input type="submit" name="Submit" value="Multiply" />
</form>
<Table number={number} />
</div>
);
}
}
export default App;
So my initial idea was to try to test the multiply function. And did this, which obviously doesn't work
import App from "../src/App";
test("Multiply", function() {
const expected = 21;
const result = App.handleMultiply(3, 7);
expect(result).toBe(expected);
});
I get
_App.default.handleMultiply is not a function
Is my approach right? If yes then how do I test the functions? Else, should I test from a user point of view instead of for internal functions (this is what I read)? Should I test for the output on the screen (I don't think this is reasonable)?
解决方案
You can use instance() method of enzyme
to get the instance of React Component. Then, call handleMultiply
method directly and make the assertion for it. Furthermore, if the handleMultiply
method has a side-effect or very complicated calculations, you need to make a simple mocked return value for it. It will make an isolated test environment for handleSubmit
method. This means handleSubmit
method will not depend on the return value of the real implementation of handleMultiply
method.
E.g.
app.jsx
:
import React from 'react';
import { Table } from './table';
class App extends React.Component {
constructor(props) {
super(props);
this.state = { number: 0 };
}
handleSubmit = (number1, number2) => {
this.setState({ number: this.handleMultiply(number1, number2) });
};
handleMultiply = (number1, number2) => {
return number1 * number2;
};
render() {
const { number } = this.state;
return (
<div className="App">
<form onSubmit={(e) => this.handleSubmit(3, 7)}>
<input type="submit" name="Submit" value="Multiply" />
</form>
<Table number={number} />
</div>
);
}
}
export default App;
table.jsx
:
import React from 'react';
export const Table = ({ number: num }) => {
return <div>table: {num}</div>;
};
app.test.jsx
:
import App from './app';
import { shallow } from 'enzyme';
describe('59796928', () => {
let wrapper;
beforeEach(() => {
wrapper = shallow(<App></App>);
});
describe('#handleSubmit', () => {
it('should pass', () => {
expect(wrapper.exists()).toBeTruthy();
wrapper.find('form').simulate('submit');
expect(wrapper.state()).toEqual({ number: 21 });
});
});
describe('#handleMultiply', () => {
it('should pass', () => {
const comp = wrapper.instance();
const actual = comp.handleMultiply(2, 10);
expect(actual).toBe(20);
});
});
});
Unit test results with coverage report:
PASS src/stackoverflow/59796928/app.test.jsx (11.688s)
59796928
#handleSubmit
✓ should pass (16ms)
#handleMultiply
✓ should pass (9ms)
-----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files | 90.48 | 100 | 85.71 | 94.44 | |
app.jsx | 100 | 100 | 100 | 100 | |
table.jsx | 50 | 100 | 0 | 66.67 | 4 |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 13.936s
Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/59796928
推荐阅读
- html - Chrome 在 iPhone 上的页面周围添加了一个缺口
- r - 在 R 中使用带有比例/百分比因变量的 glmrob 函数
- winforms - Windows 服务无法打开 Windows 窗体
- javascript - 如何在 JavaScript 中做这个数学公式
- ios - 如何在 swift 5 中获取 MusicSequenceSetUserCallback?
- python - 使用python在sql文件中使用正则表达式自动删除字符
- sql - 选择两列小于10的字符
- c# - 执行后如何退出函数
- database - 如何在不损害封装的情况下填充嵌套数据库?
- django - django.db.utils.OperationalError: (1091, "Can't DROP 'company_id'; 检查列/键是否存在")