Next.js + Jest测试报错:Listbox组件类型无效问题求助
Next.js单元测试中@headlessui/react的Listbox组件渲染错误
我在为Next.js项目配置单元测试时,遵循了官方的Jest和React Testing Library配置步骤,但运行测试时遇到了与@headlessui/react库相关的渲染错误。该组件在项目运行和构建阶段均能正常工作,仅测试时出错。
错误信息
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
Check the render method ofListbox.
项目配置详情
tsconfig.json
{ "compilerOptions": { "target": "ES6", "lib": ["dom", "dom.iterable", "esnext"], "baseUrl": "./", "allowJs": true, "skipLibCheck": true, "strict": true, "exactOptionalPropertyTypes": true, "noImplicitReturns": true, "noUnusedLocals": true, "noUnusedParameters": true, "forceConsistentCasingInFileNames": true, "removeComments": true, "noEmit": true, "esModuleInterop": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", "incremental": true }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], "exclude": ["node_modules"] }
jest.config.mjs
import nextJest from 'next/jest.js'; const createJestConfig = nextJest({ dir: './', }); /** @type {import('jest').Config} */ const config = { setupFilesAfterEnv: ['<rootDir>/jest.setup.js'], testEnvironment: 'jest-environment-jsdom', moduleDirectories: ['node_modules', '<rootDir>/'], testMatch: ['**/*.(test|spec).(js|jsx|ts|tsx)'], coveragePathIgnorePatterns: ['/node_modules/'], }; export default createJestConfig(config);
next.config.js
/** @type {import('next').NextConfig} */ const nextConfig = { images: { remotePatterns: [{ protocol: 'https', hostname: '**.pixabay.com' }], }, reactStrictMode: true, webpack(config) { config.module.rules.push({ test: /\.svg$/, use: ['@svgr/webpack'], }); return config; }, }; module.exports = nextConfig;
package.json
{ "name": "cw-client", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint", "typescript": "tsc", "test": "jest", "test:ci": "jest --ci" }, "engines": { "node": ">=19.3.0" }, "dependencies": { "@dnd-kit/core": "^6.0.7", "@dnd-kit/modifiers": "^6.0.1", "@dnd-kit/sortable": "^7.0.2", "@dnd-kit/utilities": "^3.2.1", "@headlessui/react": "^1.7.7", "@next/font": "13.1.1", "lodash.debounce": "^4.0.8", "mathjs": "^11.6.0", "next": "13.1.1", "react": "18.2.0", "react-dom": "18.2.0", "react-number-format": "^5.1.4" }, "devDependencies": { "@next/eslint-plugin-next": "^13.1.1", "@svgr/webpack": "^6.5.1", "@tailwindcss/forms": "^0.5.3", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^14.0.0", "@types/lodash.debounce": "^4.0.7", "@types/node": "18.11.17", "@types/react": "18.0.26", "@types/react-dom": "18.0.10", "@typescript-eslint/eslint-plugin": "^5.47.0", "@typescript-eslint/parser": "^5.47.0", "autoprefixer": "^10.4.13", "eslint": "8.30.0", "eslint-config-next": "13.1.1", "eslint-config-prettier": "^8.5.0", "eslint-plugin-import": "^2.26.0", "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-react": "^7.31.11", "jest": "^29.5.0", "jest-environment-jsdom": "^29.5.0", "postcss": "^8.4.20", "prettier": "2.8.1", "prettier-plugin-tailwindcss": "^0.2.1", "tailwindcss": "^3.3.1", "typescript": "4.9.4" } }
测试代码(位于__tests__/components)
import { render, screen } from '@testing-library/react'; import { ListType } from 'components/calculator/builder/utils/types/list'; import List from 'components/ui/fields/list/list'; jest.mock('components/calculator/context/hooks', () => ({ // ... mock custom hook. })); const mockList: ListType = { // ... mock data }; const renderComponent = () => { render(<List list={mockList} />); }; describe('List component', () => { test('check if the correct list options are displayed', () => { renderComponent(); expect(screen.getAllByRole('option')).toHaveLength(mockList.options.length); expect(screen.getByText(mockList.description)).toBeInTheDocument(); expect(screen.getByText(mockList.placeholder)).toBeInTheDocument(); }); });
被测试组件代码片段
import { Listbox } from '@headlessui/react'; // <= 从node_modules导入的Listbox // 其他内部导入 interface ListProps { list: ListType; } export default function List({ list }: ListProps) { return ( <Listbox> // ...实现细节无关 </Listbox>) }
已尝试的解决方案
- 排查导入方式:确认没有混用默认导出与命名导入,组件正常运行也验证了这一点
- 检查组件返回值:确保返回有效JSX,错误信息显示得到的是
object而非undefined,不符合此类问题特征 - 排除路径别名影响:项目未使用路径别名,无需配置tsconfig的
path和jest相关设置 - 在组件顶部导入React
- 将
export default移至组件底部 - 测试Next.js样板仓库:样板仓库中该组件可正常测试,但现有项目规模较大无法重建
内容的提问来源于stack exchange,提问作者Zenik
相关产品推荐
相关产品推荐

