【发布时间】:2019-12-10 23:32:05
【问题描述】:
我正在尝试学习测试,从基本测试开始,现在我想测试功能。但是,我浏览了所有感觉的互联网,但我无法测试 onClick 的东西。也许我什么都看不出来。
我尝试过使用 sinon.spy、jest spyOn 等。但这些都没有成功。
测试,我正在写。
import React from "react";
import {
shallow,
configure
} from "enzyme"
import Adapter from "enzyme-adapter-react-16";
import ConfirmDeleteButton from "../ConfirmDeleteButton"
import { Modal } from "react-bootstrap"
import sinon from "sinon"
import toJson from "enzyme-to-json";
configure({adapter: new Adapter()});
let wrapper;
const fnClick = sinon.spy();
// Assign component to wrapper variable, before all tests.
beforeEach(() => {
wrapper = shallow(<ConfirmDeleteButton onClick={fnClick} />)
});
describe("ConfirmDeleteButton component", () => {
it('should call mockfn onclick', () => {
//simulate onClick
wrapper
.find("Button").first()
.prop("onClick")()
expect(fnClick).toBeCalled();
})
})
组件,我正在测试:
import React, { useState } from 'react'
import PropTypes from 'prop-types'
import { Button, Spinner, Modal } from 'react-bootstrap'
import { Mutation } from 'react-apollo'
const ConfirmDeleteButton = props => {
const [confirmDelete, setConfirmDelete] = useState(false)
const [timeout, setTimeoutState] = useState()
const [show, setShow] = useState(false)
const confirmButtonRef = React.createRef()
const handleClose = () => setShow(false)
const handleShow = () => setShow(true)
return (
<React.Fragment>
<Button variant='outline-danger' onClick={handleShow} id='openModal'>
Delete
</Button>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Confirmation dialog</Modal.Title>
</Modal.Header>
<Modal.Body>
Are you sure you want to delete this item?
This item will be gone permanently, and can cause cascade delete!
</Modal.Body>
<Modal.Footer>
<Button variant='outline-secondary' onClick={handleClose} id='closeModal'>
Close
</Button>
{confirmDelete ? (
<Mutation
mutation={props.deleteMutation}
// refetchQueries triggers parent component to be loaded with new data
refetchQueries={props.refetchQueries}
onCompleted={() => {
if (props.onCompleted) {
props.onCompleted()
}
setConfirmDelete(false)
}}
>
{(deleteFunction, { loading, error }) => (
<Button
variant='danger'
ref={confirmButtonRef}
onClick={() => {
let vars = {}
if (props.variables) {
for (let key in props.variables) {
vars[key] = props.variables[key]
}
} else {
vars['ID'] = props.id
}
deleteFunction({ variables: vars })
clearTimeout(timeout)
confirmButtonRef.current.blur()
handleClose()
}}
>
{loading ? <Spinner animation='border' as='span' size='sm' /> : 'Confirm'}
</Button>
)}
</Mutation>
) : (
<Button
variant='outline-success'
onClick={() => {
setConfirmDelete(true)
setTimeoutState(
setTimeout(function() {
setConfirmDelete(false)
}, 3000)
)
}}
>
Yes
</Button>
)}
</Modal.Footer>
</Modal>
</React.Fragment>
)
}
ConfirmDeleteButton.propTypes = {
onCompleted: PropTypes.func,
variables: PropTypes.object,
deleteMutation: PropTypes.object,
refetchQueries: PropTypes.array
}
export default ConfirmDeleteButton
最后,我想测试一下: *如果点击按钮调用handleShow
现在我开始了:
ConfirmDeleteButton component › should call mockfn onclick
expect(jest.fn())[.not].toBeCalled()
Matcher error: received value must be a mock or spy function
Received has type: function
Received has value: [Function anonymous]
我会添加 package.json 以防万一:
"devDependencies": {
"@babel/core": "^7.1.6",
"@babel/plugin-transform-runtime": "^7.5.0",
"@babel/preset-env": "^7.1.6",
"@babel/preset-es2015": "^7.0.0-beta.53",
"@babel/preset-react": "^7.0.0",
"@material-ui/core": "^4.2.0",
"apollo-boost": "^0.4.3",
"autoprefixer": "^9.6.1",
"babel-jest": "^24.8.0",
"babel-loader": "^8.0.6",
"babel-plugin-transform-export-extensions": "^6.22.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-stage-3": "^6.24.1",
"bootstrap": "^4.3.1",
"chai": "^4.2.0",
"chai-enzyme": "^1.0.0-beta.1",
"copy-webpack-plugin": "^5.0.3",
"css-loader": "^3.0.0",
"dotenv": "^8.0.0",
"dotenv-webpack": "^1.7.0",
"enzyme": "^3.10.0",
"enzyme-adapter-react-15": "^1.4.0",
"enzyme-adapter-react-16": "^1.14.0",
"enzyme-to-json": "^3.3.5",
"eslint": "^6.0.1",
"eslint-cli": "^1.1.1",
"eslint-config-airbnb": "^17.1.1",
"eslint-config-airbnb-base": "^13.2.0",
"eslint-config-prettier": "^6.0.0",
"eslint-loader": "^2.2.1",
"eslint-plugin-prettier": "^3.1.0",
"extract-text-webpack-plugin": "^3.0.2",
"file-loader": "^4.0.0",
"graphql": "^14.4.2",
"html-webpack-plugin": "^3.2.0",
"jest": "^24.8.0",
"mini-css-extract-plugin": "^0.7.0",
"node-sass": "^4.12.0",
"prettier": "^1.18.2",
"react": "^16.8.6",
"react-apollo": "^2.5.8",
"react-bootstrap": "^1.0.0-beta.9",
"react-dom": "^16.8.6",
"react-hot-loader": "^4.12.6",
"react-router-dom": "^5.0.1",
"react-scripts": "^3.0.1",
"react-test-renderer": "^16.8.6",
"sass-loader": "^7.1.0",
"sinon": "^7.3.2",
"sinon-chai": "^3.3.0",
"style-loader": "^0.23.1",
"ts-jest": "^24.0.2",
"uglifyjs-webpack-plugin": "^2.1.3",
"uuid": "^3.3.2",
"webpack": "^4.35.3",
"webpack-bundle-tracker": "^0.4.2-beta",
"webpack-cli": "^3.3.5",
"webpack-dev-server": "^3.7.2"
},
"dependencies": {
"@babel/core": "^7.5.4"
}
【问题讨论】:
-
试试
.find(Button)(不带引号)。字符串变体仅适用于 CSS 选择器,仅适用于<button>或 ` 等原生元素 -
那么按钮是未定义的。如果我尝试 .find(#id),它的效果与 .find("Button") 相同。
-
抱歉,我只是想尽快回复,以解决这个问题。是的,忘记导入了,但问题似乎还是一样。
-
哦,抱歉,一开始没有完全阅读代码。我看不到您如何在组件中使用
props.onClick。所以预计您的jest.fn在单击按钮后不会被调用 - 因为没有任何调用。 -
但是在记录 Button.props() 时,里面有带有 onClick: [function handleShow] 的 props 对象。我认为它应该工作,但我只是不知道为什么..
标签: reactjs jestjs enzyme react-hooks react-bootstrap