Rah*_*hul 27 unit-testing reactjs react-testing-library react-query
我正在使用反应测试库处理测试用例。为了编写测试用例,我需要模拟 React 查询的 useQuery 和 useMutation 方法。如果有人知道解决方案,请指导我。我在这里添加相关代码。
工作空间详细信息部分.test.tsx
import React from 'react'
import '@testing-library/jest-dom'
import '@testing-library/jest-dom/extend-expect'
import { screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { WorkspaceDetailsSection } from '../WorkspaceDetailsSection'
import { render } from '../../_utils/test-utils/test-utils'
const mockedFunction = jest.fn()
let realUseContext: any
let useContextMock: any
// Setup mock
beforeEach(() => {
realUseContext = React.useContext
useContextMock = React.useContext = jest.fn()
})
// Cleanup mock
afterEach(() => {
React.useContext = realUseContext
})
jest.mock('../data', () => ({
useMutationHook: () => ({ mutate: mockedFunction })
}))
const WorkspaceContext = {
workspaceInfo: {
name: 'name',
dot: 'name',
type: 'type'
}
}
test('renders section with the valid details', async () => {
useContextMock.mockReturnValue(WorkspaceContext)
render(<WorkspaceDetailsSection />)
expect(screen.getByText('Workspace name:')).toBeInTheDocument()
})
Run Code Online (Sandbox Code Playgroud)
工作空间详细信息部分.tsx
import React, { useContext } from 'react'
import { FormModal, useDisclosure } from '@chaine/keychaine'
import { workspaceService } from './data'
import { useMutation } from 'react-query'
import { Section } from '../account-settings'
import { Toast } from '../_shared/components'
import { IWorkspace } from '../_shared/refactoredInterfaces'
import constant from '../_shared/constants/message'
import { WorkspaceContext } from './WorkspacePage'
import capitalizeFirstLetter from '../_utils/capitalizeFirstLetter'
import { queryClient } from '../_shared/infra'
/**
*
* should import section component and return that
*/
export const WorkspaceDetailsSection = () => {
const { isOpen, onOpen, onClose } = useDisclosure()
const { workspaceInfo } = useContext(WorkspaceContext)
const { name, dot, type } = workspaceInfo
const { showToast } = Toast()
const updateWorkspace = useMutation((params: any) => workspaceService.updateWorkspace(params))
const handleSubmit = async (event: any) => {
const params: IWorkspace = {
...event,
id: workspaceInfo.id,
type: event.type.value
}
updateWorkspace.mutate(params, {
onSuccess: () => {
onClose()
queryClient.invalidateQueries('WorkspaceProfile')
},
onError: () => {
showToast({
title: constant.UNABLE_TO_UPDATE_WORKSPACE,
status: 'error'
})
}
})
}
return (
<>
<Section
sectionTitle={'Workspace details'}
multipleFields={[
{ fieldName: 'Workspace name:', value: name },
{ fieldName: 'Workspace type:', value: type },
{ fieldName: 'DOT #:', value: dot }
]}
buttonName={'Edit details'}
onClick={() => onOpen()}
/>
<FormModal
isOpen={isOpen}
onClose={() => onClose()}
title={'Change workspace info'}
size={'lg'}
formSubmitHandler={handleSubmit}
isLoading={updateWorkspace.isLoading}
initialValues={{
dot: dot,
type: { label: capitalizeFirstLetter(type), value: type },
name: name
}}
modalItems={[
{
name: 'name',
type: 'input',
placeHolder: 'Enter you name',
labelText: 'Workspace display name'
},
{ name: 'dot', type: 'input', placeHolder: 'Enter you DOT #', labelText: 'DOT #' },
{
name: 'type',
type: 'select',
placeHolder: type,
labelText: 'Workspace type',
selectOptions: [
{ label: 'Carrier', value: 'carrier' },
{ label: 'Broker', value: 'broker' },
{ label: 'Shipper', value: 'shipper' }
]
}
]}
/>
</>
)
}
Run Code Online (Sandbox Code Playgroud)
工作区服务.ts
import { BaseAPI } from '../../_shared/infra/services/BaseAPI'
import { ITokenService, IWorkspace } from '../../_shared/refactoredInterfaces'
import { TeamResponseDTO, UpdateWorkspaceResponseDTO, UploadWorkspaceLogoResponseDTO } from './WorkspaceDTO'
export interface IWorkspaceService {
getWorkspace(): Promise<TeamResponseDTO>
updateWorkspace(params: IWorkspace): Promise<UpdateWorkspaceResponseDTO>
uploadWorkspaceLogo(params: any): Promise<UploadWorkspaceLogoResponseDTO>
}
export class WorkspaceService extends BaseAPI implements IWorkspaceService {
constructor(tokenService: ITokenService) {
super(tokenService)
}
async getWorkspace(): Promise<TeamResponseDTO> {
const body = {
url: '/users/account'
}
const { data } = await this.get(body)
return {
team: data?.data,
message: data?.message
}
}
async updateWorkspace(params: IWorkspace): Promise<UpdateWorkspaceResponseDTO> {
const body = {
url: '/accounts',
data: params
}
const { data } = await this.put(body)
return {
message: data.message
}
}
async uploadWorkspaceLogo(params: FormData): Promise<UploadWorkspaceLogoResponseDTO> {
const body = {
url: '/accounts/logos',
data: params,
headers: {
'Content-Type': 'multipart/form-data'
}
}
const response = await this.post(body)
return response
}
}
Run Code Online (Sandbox Code Playgroud)
还尝试了@TkDodo在这里提出的解决方案,但对我不起作用。这个解决方案将是我的救星,所以提前感谢你们。
小智 12
这对我有用
jest.mock('react-query', () => ({
useQuery: jest.fn().mockReturnValue(({ data: {...MockData}, isLoading: false,error:{} }))
}));
Run Code Online (Sandbox Code Playgroud)
小智 11
我发现有效的方法是监视react-query模块并模拟useQuery的实现。
import * as ReactQuery from 'react-query'
jest
.spyOn(ReactQuery, 'useQuery')
.mockImplementation(
jest
.fn()
.mockReturnValue({ data: { ...MockData }, isLoading: false, isSuccess: true })
)
Run Code Online (Sandbox Code Playgroud)
小智 4
我没有足够的声誉来回复@TkDodo上面的评论(我想,主要潜伏在SO上的“价格”),但我发现mockingreact-query的useQuery()返回值对于练习特定的渲染结果绝对有用,而无需不用担心到处都是await waitFor()s 的异步测试。
遗憾的是,我无法找到一个现成的软件包来为我管理这个问题。
也就是说,我可以报告说,我发现为我的单元测试创建一些辅助函数是有价值的,这些函数生成一个带有此处记录的解构键的对象。
函数签名如下:
export function generateUseQueryReturnValueError(error, overrides = {}) {
// use the error argument as the reported error object and make sure to
// set flags like `isSuccess`, `isError`, `isLoading` and the rest...
}
export function generateUseQueryReturnValueSuccess(data, overrides = {}) {
// use the data argument as you'd expect and, obviously, set the flags
}
export function generateUseQueryReturnValueLoading(overrides = {}) {
// same note about setting the flags correctly
}
Run Code Online (Sandbox Code Playgroud)
然而,毫无价值的是,尽管这些函数做了一些(非常轻!)“理智”检查/预防,例如确保该isError字段不能被覆盖为falsefor generateUseQueryReturnValueError(),但显然有足够的空间来实现“真实”中“不可能”的结果。生活”。
| 归档时间: |
|
| 查看次数: |
61415 次 |
| 最近记录: |