reactjs - 由于选择器未定义,Jest 单元测试失败
问题描述
我正在为一个组件编写一个测试用例,它正在使用 redux、saga 和选择器测试用例如下
const initialState = {
fetching: false,
error: null,
StockProducts: [],
products: [],
filter: '5b438ae60599132cb8b64b67'
}
const mockStore = configureStore()
const store = mockStore(fromJS(initialState))
import Stock from '../Stock'
test('for onUpdate funcion', () => {
const props = {
setErrorPopUp: jest.fn(),
formSubmitAttempt: jest.fn()
}
const wrapper = shallow(<Stock {...props} store={store} />)
wrapper.instance().onUpdate({ quantity: 0 })
expect(props.setErrorPopUp).toHaveBeenCalled()
wrapper.instance().onUpdate({ quantity: 3 })
expect(props.formSubmitAttempt).toHaveBeenCalled()
})
但是测试失败了,我收到了这个错误
TypeError: Cannot read property 'fetching' of undefined
12 | createSelector(
13 | selectStockDomain,
> 14 | ({ fetching }) => fetching
15 | )
16 |
17 | const StockError = () =>
那是来自我用于组件的选择器之一 我的测试出了什么问题,为什么会发生这种情况以及我该如何解决这个问题
这是库存组件
// react core
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { createStructuredSelector } from 'reselect'
// component imports
// Selcetors and actions
import StockActions from './actions'
import ToastActions from 'containers/Toasts/actions'
import {
StockFetching,
StockError,
StockProducts,
StockFilter,
Products,
userData
} from './selectors'
// partials
const mapStateToProps = createStructuredSelector({
fetching: StockFetching(),
error: StockError(),
stockProducts: StockProducts(),
products: Products(),
filter: StockFilter(),
userData: userData()
})
const mapDispatchToProps = dispatch => ({
getStockProducts: () => {
dispatch(StockActions.getStockAttempt())
},
getProducts: payload => {
dispatch(StockActions.getProductsAttempt(payload))
},
formSubmitAttempt: payload => {
dispatch(StockActions.formSubmitAttempt(payload))
},
deleteStock: payload => {
dispatch(StockActions.deleteStockAttempt(payload))
},
setErrorPopUp: payload => {
dispatch(
ToastActions.setToast(payload.message, payload.action, payload.time)
)
},
reset: () => {
dispatch(StockActions.reset())
}
})
class Stock extends Component {
state = {
openCard: false,
showCard: false,
confirmDelete: false
}
// to show product details
onCard = openCard => {
this.setState({
openCard
})
}
// to show and close add to stock option
_ShowCard = () => {
this.setState({
showCard: !this.state.showCard
})
}
// onDlete Stock
onDeleteStock = data => {
let {
props: { deleteStock },
state: { confirmDelete }
} = this
if (confirmDelete) {
deleteStock(data)
this.setState({
confirmDelete: false
})
} else {
this.setState({
confirmDelete: true
})
}
}
// update the products
handlesubmit = data => {
if (parseInt(data.quantity) < 1) {
this.props.setErrorPopUp({
message:
'You cannot set quantity to zero.Please enter valid qunatity and try again',
action: 'danger',
time: '5000'
})
} else {
this.props.formSubmitAttempt({
product: data.product.key,
quantity: data.quantity
})
this._ShowCard()
}
}
onUpdate = data => {
if (parseInt(data.quantity) < 1) {
this.props.setErrorPopUp({
message: 'You cannot set quantity to zero.Use delete actions',
action: 'danger',
time: '5000'
})
} else {
this.props.formSubmitAttempt({
product: data.id,
quantity: data.quantity
})
}
}
onCancelDelete = () => {
this.setState({
confirmDelete: false
})
}
onGetStock = () => {
let { getStockProducts, getProducts, userData } = this.props
getStockProducts()
getProducts({ user: userData._id })
}
componentDidMount () {
this.onGetStock()
}
render () {
let {
props: { stockProducts, error, products, fetching },
state: { openCard, showCard, confirmDelete },
onCard,
onGetStock,
_ShowCard,
handlesubmit,
onUpdate,
onDeleteStock,
onCancelDelete
} = this
return (
<KeyboardAvoidingWrapper fluid enabled={!showCard}>
UI GOES HERE ....
</KeyboardAvoidingWrapper>
)
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(Stock)
谢谢
解决方案
当您测试一个组件时,最好只测试组件的行为,而与您的 redux 存储无关。因为,在内部,商店将状态作为道具传递给组件。
1.export
你的组件
所以你的组件定义代码变成
class Stock extends Component {
至
export class Stock extends Component {
2.import
只是没有 Connect HOC 的组件
像这样
import { Stock } from '../Stock'
test('for onUpdate funcion', () => {
const props = {
setErrorPopUp: jest.fn(),
formSubmitAttempt: jest.fn()
}
const wrapper = shallow(<Stock {...props} />)
// modify your code to see how your component behaves with different props
wrapper.instance().onUpdate({ quantity: 0 })
expect(props.setErrorPopUp).toHaveBeenCalled()
wrapper.instance().onUpdate({ quantity: 3 })
expect(props.formSubmitAttempt).toHaveBeenCalled()
})
推荐阅读
- magento - 您如何在 Magento 网站上 301 重定向 404 错误?
- javascript - 在形状路径上写入文本
- java - 将 TextFlow 添加到 FXML 控制器会使 GUI 变为空白
- python - 没有 distutils.version 的 Python 版本列表
- c# - 调用 System.Diagnostics.Process.GetProcesses() 未返回 C# 最小化窗口
- xcode - 有什么方法可以从终端为 Xcode 添加新的启动图像
- docker - 使用主机库的 Docker
- jquery - 如何在 JavaScript 闭包中使用全局变量?
- css - 为什么我的浮动边距底部不正确?
- sql-server - Go 数据库客户端杀死与 SQL Server 的连接比预期的要多