我将 formik 和 useDispatch 用于表单和提交功能。仅当我注释掉 API 调用代码时,我才能够测试该操作是否在提交时分派。如果我不注释掉,则会引发错误。
如何调用模拟 API 调用而不是实际 API?或者如何使用 redux-mock-store 进行formik+异步 API 调用?
忘记密码.js:
<>
<Typography variant='h6'>Recover Password</Typography>
<Formik
initialValues={{ username: '' }}
onSubmit={(values, { setSubmitting }) => {
dispatch(forgotPassword(values.username)).then(() => {
setSubmitting(false)
})
}}
validationSchema={validations}
>
<Form noValidate>
<Field
name='forgotPassword'
render={formikProps => (
<>
<Field
variant='outlined'
margin='normal'
required
fullWidth
id='username'
label='Username'
name='username'
autoComplete='username'
component={TextField}
autoFocus
/>
<Button type='submit' />
</>
)}
/>
</Form>
</Formik>
</>
忘记密码.test.js
import React from 'react'
import ForgotPassword from '../../components/public/ForgotPassword'
import { mount } from 'enzyme'
import { Provider } from 'react-redux'
import configureStore from 'redux-mock-store'
import * as ReactReduxHooks from '../react-redux-hooks'
import thunk from 'redux-thunk'
describe('#ForgotPassword', () => {
let wrapper
const middleWare = [thunk]
const mockStore = configureStore(middleWare)
let store
beforeEach(() => {
const initialState = {
auth: { tempUsername: '' },
}
store = mockStore(initialState)
jest
.spyOn(ReactReduxHooks, 'useSelector')
.mockImplementation(state => store.getState())
jest
.spyOn(ReactReduxHooks, 'useDispatch')
.mockImplementation(() => store.dispatch)
wrapper = mount(
<Provider store={store}>
<ForgotPassword />
</Provider>
)
})
it('expect value changes after simulate change', async () => {
wrapper.find('input').simulate('change', {
persist: () => {},
target: { value: 'jhonny123', name: 'username' },
})
expect(wrapper.find('input').props().value).toBe('jhonny123')
wrapper.find('button').simulate('submit')
await new Promise(resolve => {
setTimeout(() => resolve(), 0)
})
const actions = store.getActions()
console.log(actions)
//when the API call part, is commented out inside the actions, prints the actions nicely
//and if I don't comment out the API call part, throws an error
})
})
调度的动作
export const forgotPassword = username => {
return async dispatch => {
dispatch(setTempUsername(username))
// await Auth.forgotPassword(username)
// .then(() => {
// dispatch(setResettingPassword(true))
// })
// .catch(err => {
// /*dispatch(showError(err.message)*/
// })
dispatch(
showSuccess(
'A verification code has been sent to the email linked to your username.'
)
)
}
}
这是在操作中注释掉 API 调用部分时的 console.log
[
{ type: 'auth/setTempUsername', payload: 'jhonny123' },
{
type: 'snackbar/handleSnackbar',
payload: {
verticalPosition: 'bottom',
horizontalPosition: 'center',
message: 'A verification code has been sent to the email linked to your username.',
autoHideDuration: 10000,
messageType: 'success',
isOpen: true
}
}
]
api调用未注释掉时出错
TypeError: Cannot read property 'clientMetadata' of undefined
407 | return async dispatch => {
408 | dispatch(setTempUsername(username))
> 409 | await Auth.forgotPassword(username)
| ^
410 | .then(() => {
411 | dispatch(setResettingPassword(true))
412 | })