我正在尝试使用 Vitest 为我的 React 应用程序设置测试,但我遇到了一个错误,这一定是由于我的测试套件中缺少某些依赖项或错误造成的。我不确定到底是什么原因。当我尝试运行测试时,出现以下错误:
TypeError: Cannot read properties of null (reading 'useRef')
它说它发生在我的登录组件中,其中包含来自
react-hook-form
的钩子。
export default function Login() {
const { register, handleSubmit } = useForm();
^
当我删除这条明显有问题的行时,它会在其他地方引起类似的问题,它说
useReducer
的实例是 null
。
这就是我的 setupTests.js 的样子:
import { server } from './mocks/server';
import '@testing-library/jest-dom';
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
这是我的 Vite 配置:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
test: {
globals: true,
environment: 'jsdom',
setupFiles: './src/setupTests.js',
}
})
这是我的 package.json:
{
"name": "my-project",
"private": true,
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"knex": "knex",
"test": "vitest"
},
"dependencies": {
"bcrypt": "^5.0.1",
"cloudinary": "^1.30.0",
"connect-session-knex": "^3.0.0",
"cors": "^2.8.5",
"dotenv": "^16.0.1",
"express": "^4.18.1",
"express-session": "^1.17.3",
"knex": "^2.0.0",
"multer": "^1.4.5-lts.1",
"passport": "^0.5.3",
"passport-local": "^1.0.0",
"pg": "^8.7.3",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-hook-form": "^7.31.2",
"react-router-dom": "^6.3.0",
"sass": "^1.51.0",
"vitest": "^0.16.0"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^14.2.1",
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"@vitejs/plugin-react": "^1.3.0",
"jsdom": "^20.0.0",
"msw": "^0.42.3",
"vite": "^2.9.9"
}
}
所有这些钩子在测试之外都工作得很好,所以我不确定为什么它们是未定义的。
我尝试安装
@testing-library/react-hooks
希望它可以解决我的问题,但我无法这样做,因为它似乎不支持 React 18。
非常感谢您的支持。
我遇到了完全相同的问题,所以我进行了一些调查,并找到了一个可行的解决方案。
@testing-library/react
> 13.1使用
renderHook
包中的 @testing-library/react
方法并用它包裹你的钩子:
import React from 'react';
import { render, renderHook, screen } from '@testing-library/react';
import { describe, test } from 'vitest';
import { FormProvider, useForm } from 'react-hook-form';
describe('Input', () => {
test('should render an Input component', () => {
type FormValues = {
field: string;
};
const { result } = renderHook(
() => useForm<FormValues>({
defaultValues: {
field: '',
},
})
);
const methods = result.current;
const { register } = methods;
render(
<FormProvider {...methods}>
<form>
<input {...register('field')} data-testid="my-field" />
</form>
</FormProvider>
);
expect(screen.getByTestId('my-field').toHaveAttribute('name', 'field'));
});
});
首先,钩子不起作用的原因是因为我们处于测试环境中,所以我们使用的函数需要被模拟。
@testing-library
提供了能够使用钩子的解决方案。由于@testing-library/react@^13.1
,包@testing-library/react-hooks
就没用了,你可以在这里阅读:https://www.npmjs.com/package/@testing-library/react-hooks#user-content-a-note-about-反应-18-支持
假设我们使用 React Hook Form 和 Vitest 有一个这样的测试:
import React from 'react';
import { describe, test } from 'vitest';
import { FormProvider, useForm } from 'react-hook-form';
describe('Input', () => {
test('should render an Input component', () => {
type FormValues = {
field: string;
};
const methods = useForm<FormValues>({ defaultValues: { field: '' } });
const { register } = methods;
render(
<FormProvider {...methods}>
<form>
<input {...register('field')} data-testid="my-field" />
</form>
</FormProvider>
);
expect(screen.getByTestId('my-field').toHaveAttribute('name', 'field'));
});
});
此测试将崩溃并出现以下错误:
TypeError: Cannot read properties of null (reading 'useRef')
要使其正常工作,请添加此导入:
import { renderHook } from '@testing-library/react';
并将之前的
useForm
React Hook Form 钩子替换为:
const { result } = renderHook(
() => useForm<FormValues>({
defaultValues: {
field: ''
},
})
);
const methods = result.current;
现在测试运行良好🥳
@testing-library/react@^13.1
运行以下命令将
@testing-library/react-hooks
添加到您的项目中:
npm i --save-dev @testing-library/react-hooks
并从刚刚安装的包中导入
renderHook
import { renderHook } from '@testing-library/react-hooks`
可以在此处找到文档:https://www.npmjs.com/package/@testing-library/react-hooks#table-of-contents
当我添加
react
插件后,这个问题就会消失
import react from '@vitejs/plugin-react';
import { defineConfig } from 'vitest/config';
export default defineConfig({
plugins: [react()],
});