reactjs - 使用 useEffect 和 useState 在 React 组件中测试 Mock Async Deta Fetching
问题描述
我有一个组件,它在 useEffect 中获取一些数据,并使用 useState 函数通过响应设置状态。这似乎是一个非常惯用的模式,但我没有太多运气弄清楚如何测试它。在这种情况下,QuarantineApi.getQuarantinedFileLogs
返回一个可以解析为我需要的数据数组的承诺。这就是我想嘲笑的;底层实现(axios 或 fetch)应该无关紧要。
import React, {useEffect, useState} from 'react'
import {FormGroup, Input, Label, Table} from 'reactstrap'
import {QuarantinedFileLog} from '../QuarantinedFileLog'
import {DeleteQuarantinedFileButton} from './DeleteQuarantinedFileButton'
import {DownloadQuarantinedFileButton} from './DownloadQuarantinedFileButton'
import {UploadQuarantinedFileButton} from './UploadQuarantinedFileButton'
import QuarantineApi from '../../../api/QuarantineApi'
// @ts-ignore
import {GMTLoadingIndicator} from '@gmt/coreui-react'
interface IQuarantinedFilesListProps {
}
export const QuarantinedFilesList = (props: IQuarantinedFilesListProps) => {
const {getQuarantinedFileLogs} = QuarantineApi
const [loading, setLoading] = useState(true)
const [quarantinedFiles, setQuarantinedFiles] = useState<QuarantinedFileLog[]>([])
const [quarantineServiceError, setQuarantineServiceError] = useState<string|null>(null)
useEffect(() => {
getQuarantinedFileLogs().then(
(returnedQuarantinedFileLogs) => {
setQuarantinedFiles(returnedQuarantinedFileLogs)
setLoading(false)
}
).catch(
error => {
setQuarantineServiceError(`There was a problem getting quarantined files ${error}`)
setLoading(false)
}
)
}, [getQuarantinedFileLogs])
return (
<>
{quarantineServiceError && (
<div className="alert alert-danger" role="alert">
{quarantineServiceError}
</div>
)}
{loading && <GMTLoadingIndicator />}
{!loading && !quarantinedFiles.length && (
<p>No quarantined files</p>
)}
{!loading && !!quarantinedFiles.length && (
<Table>
<thead>
<tr>
<th></th>
<th>Filename</th>
<th>Time</th>
<th>Error</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{quarantinedFiles.map(quarantinedFileLog => {
return (
<tr key={quarantinedFileLog.id}>
<td>
<FormGroup check>
<Input type="checkbox" name="check" id="exampleCheck" />
</FormGroup>
</td>
<td>
<Label for="exampleCheck" check>{quarantinedFileLog.fileName}</Label>
</td>
<td>Date time</td>
<td>{quarantinedFileLog.errorReason}</td>
<td>
<DeleteQuarantinedFileButton
fileName={quarantinedFileLog.fileName}
/>
<span className="ml-2">
<DownloadQuarantinedFileButton />
</span>
<span className="ml-2">
<UploadQuarantinedFileButton />
</span>
</td>
</tr>
)
})}
</tbody>
</Table>
)}
</>
)
}
这是我在这里找到的最接近我想要完成的示例(改编自我的代码来自此Stack Overflow 帖子):
import renderer, { act } from 'react-test-renderer'
import {QuarantinedFilesList} from '../QuarantinedFilesList'
import React from 'react'
import {QuarantinedFileLog} from '../QuarantinedFileLog'
import QuarantineApi from '../../../api/QuarantineApi'
describe('QuarantinedFilesList', () => {
it('renders correctly', async () => {
const quarantinedFileLogs: QuarantinedFileLog[] = [
{
id: 1,
fileName: 'file 1',
errorReason: 'error 1',
queueName: 'queue 1'
},
{
id: 2,
fileName: 'file 2',
errorReason: 'error 2',
queueName: 'queue 2'
},
{
id: 3,
fileName: 'file 3',
errorReason: 'error 3',
queueName: 'queue 3'
}
]
const quarantineApiSpy = jest.spyOn(QuarantineApi, 'getQuarantinedFileLogs')
.mockResolvedValueOnce(quarantinedFileLogs)
let component
await act(async () => {
component = renderer.create(<QuarantinedFilesList />)
})
expect(quarantineApiSpy).toBeCalled()
expect(component.toJSON()).toMatchSnapshot()
})
})
我得到的错误TypeError: Cannot read property 'get' of undefined
来自应用程序的其他地方,如果我不模拟响应就不会发生。
解决方案
推荐阅读
- javascript - 点击标记点 Forge
- python - 没有流量时如何将 Google App Engine 实例缩减到 0?
- chart.js - 在条形图中,可以使较低的数字具有较高的条形吗?
- javascript - 如何将参数传递给后续函数调用?
- python - 我有一个带有空格的导出文件,我想将该文件更改为带有连字符
- sass - 为什么SASC编译器不喜欢§符号
- python - 如何更改 PyTorch 中的 DataLoader 以读取一张图像进行预测?
- vb.net - RichTextBox ClickedLink 值
- javascript - 使用一个变量来命名另一个变量javascript
- c# - AR FOUNDATION RAYCASTING:使用 RayCast 确定 Z 位置的放置位置