javascript - 如何测试使用钩子且不返回 JSX 的 ReactJS 函数
问题描述
我正在尝试在 React 中进行功能测试,但我遇到了一些障碍,我希望有人能对此有所了解。目前,我有一个小计数器应用程序,它有一个按钮组件,它接收一个函数和一个字符串作为道具。看起来像这样:
按钮.js
import React from 'react'
import PropTypes from 'prop-types'
export const Button = (props) => {
const { btnTitle, btnAction } = props
return (
<button onClick={btnAction}>{btnTitle}</button>
)
}
Button.propTypes = {
btnAction: PropTypes.func,
btnTitle: PropTypes.string
}
我还有一个 helpers 目录,其中包含我的 CounterHandler 函数,该函数接收一个数字作为计数器初始值,并且可以增加或减少所述初始值。代码如下所示:
CounterHandler.js
import React from 'react'
export const CounterHandler = num => {
const [counter, setCounter] = React.useState(num)
const increase = () => setCounter(counter + 1)
const decrease = () => setCounter(counter - 1)
return {
counter,
increase,
decrease
}
}
现在我的 App.js 呈现按钮和操作代码如下所示。
应用程序.js
import React from 'react'
import CounterHandler from './components/button/helpers'
import Button from './components/button'
function App () {
const counter = CounterHandler(0)
return (
<div className="App">
<Button btnTitle="click to increase" btnAction={counter.increase} />
<Button btnTitle="click to decrease" btnAction={counter.decrease} />
<h1>counter: {counter.counter}</h1>
</div>
)
}
export default App
该应用程序按预期工作。计数器将根据按下的按钮增加或减少。
现在我正在尝试为我的CounterHandler.js函数编写一个测试,但不幸的是,我一直遇到在本地服务器上运行应用程序时不会发生的钩子错误。
到目前为止,我想尝试的唯一测试是获取在我的计数器中找到的初始值并从那里继续。我的测试如下所示:
CounterHandler.test.js
import { CounterHandler } from './CounterHandler'
const counter = CounterHandler(0)
describe('Counter state', () => {
test('test initial state', () => {
expect(counter.counter).tobe(0)
})
})
我得到的输出是:
有人可以给我一些指示吗?我将不胜感激。
为了进一步了解我的配置,这是我在这个项目中的实验性 GitHub 帐户。https://github.com/melvinalmonte/testing-practice
谢谢!!
解决方案
如显示错误消息,useState
应在反应组件内部调用反应挂钩(等)。但是在您的测试中,您在反应组件之外调用了它。
测试这种情况的推荐方法是:不要直接测试自定义钩子,与 react 组件一起测试。
例如
app.js
:
import React from 'react';
import { CounterHandler } from './counterHandler';
function App() {
const counter = CounterHandler(0);
return (
<div className="App">
<button name="increase" onClick={counter.increase}>
click to increase
</button>
<button name="decrease" onClick={counter.decrease}>
click to decrease
</button>
<h1>counter: {counter.counter}</h1>
</div>
);
}
export default App;
counterHandler.js
:
import React from 'react';
export const CounterHandler = (num) => {
const [counter, setCounter] = React.useState(num);
const increase = () => setCounter(counter + 1);
const decrease = () => setCounter(counter - 1);
return {
counter,
increase,
decrease,
};
};
app.test.js
:
import React from 'react';
import { shallow } from 'enzyme';
import App from './app';
describe('60158977', () => {
let wrapper;
beforeEach(() => {
wrapper = shallow(<App></App>);
});
it('should render', () => {
expect(wrapper.find('h1').text()).toBe('counter: 0');
});
it('should increase counter', () => {
wrapper.find('button[name="increase"]').simulate('click');
expect(wrapper.find('h1').text()).toBe('counter: 1');
});
it('should decrease counter', () => {
wrapper.find('button[name="decrease"]').simulate('click');
expect(wrapper.find('h1').text()).toBe('counter: -1');
});
});
覆盖率 100% 的单元测试结果:
PASS stackoverflow/60158977/app.test.js
60158977
✓ should render (9ms)
✓ should increase counter (3ms)
✓ should decrease counter (1ms)
-------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-------------------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
app.js | 100 | 100 | 100 | 100 |
counterHandler.js | 100 | 100 | 100 | 100 |
-------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 3 passed, 3 total
Snapshots: 0 total
Time: 3.884s, estimated 4s
源代码:https ://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/60158977
推荐阅读
- c++ - 错误:没有匹配的函数调用构造函数初始化
- xpath - Google 电子表格 ImportHTML 表格
- react-select - 无法使用带有 Yup 库的 Formik 验证反应选择
- react-native - React Native Router Flux Actions.currentParams 道具
- linux - 如何在 Linux 中合并两个脚本,使用第二个中的一个输出
- python - AWS Athena select查询结果不定期包含数据
- sorting - 按属性对弹性搜索连续结果进行自定义排序
- sql - 在sql server的大表中添加带有udf函数的列有什么更快的方法吗?
- java - 扫描仪无法从控制台读取 int 后的字符串?
- ms-access - 一次更改多条记录的值(字段为布尔类型)