Vitest 出现类型错误:无法读取 null 的属性(读取“useRef”)

问题描述 投票:0回答:2

我正在尝试使用 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。

非常感谢您的支持。

reactjs unit-testing typeerror vite vitest
2个回答
2
投票

我遇到了完全相同的问题,所以我进行了一些调查,并找到了一个可行的解决方案。

工作解决方案
@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


0
投票

当我添加

react
插件

后,这个问题就会消失
import react from '@vitejs/plugin-react';
import { defineConfig } from 'vitest/config';

export default defineConfig({
  plugins: [react()],
});

© www.soinside.com 2019 - 2024. All rights reserved.