Remix.js+TypeScript环境下Jest测试报setState错误求助
问题描述
我正在用Remix.js搭配TypeScript开发,移除jest.config.js时测试套件能正常运行,但保留该文件就会抛出错误:"TypeError: (0 , _expect.setState) is not a function"。我必须保留这个配置文件来处理TypeScript测试的转译,目前自己排查不出问题,哪怕是极简配置也会触发这个错误。
相关代码与配置
service.test.ts
import { fetch } from '@remix-run/node' import { getGames, mapGamesData } from '../api/service' const mockFetch = fetch as jest.MockedFn<typeof fetch> const mockResponse = (mockData: any): Response => ({ json: async () => mockData } as Response) const mockGames = { data: [ { id: 857429, date: '2022-10-28T00:00:00.000Z', home_team: { id: 18, abbreviation: 'MIN', city: 'Minnesota', conference: 'West', division: 'Northwest', full_name: 'Minnesota Timberwolves', name: 'Timberwolves', }, home_team_score: 0, period: 0, postseason: false, season: 2022, status: '8:00 PM ET', time: '', visitor_team: { id: 14, abbreviation: 'LAL', city: 'Los Angeles', conference: 'West', division: 'Pacific', full_name: 'Los Angeles Lakers', name: 'Lakers', }, visitor_team_score: 0, }, { id: 857440, date: '2022-10-29T00:00:00.000Z', home_team: { id: 7, abbreviation: 'DAL', city: 'Dallas', conference: 'West', division: 'Southwest', full_name: 'Dallas Mavericks', name: 'Mavericks', }, home_team_score: 0, period: 0, postseason: false, season: 2022, status: '9:00 PM ET', time: '', visitor_team: { id: 21, abbreviation: 'OKC', city: 'Oklahoma City', conference: 'West', division: 'Northwest', full_name: 'Oklahoma City Thunder', name: 'Thunder', }, visitor_team_score: 0, }, ], meta: { total_pages: 24, current_page: 1, next_page: 2, per_page: 50, total_count: 1161, }, } jest.mock('@remix-run/node', () => ({ fetch: mockFetch, })) describe.skip('getGames', () => { beforeEach(() => { mockFetch.mockClear() }) it('should return list of games', async () => { // mockFetch.mockResolvedValue(mockResponse(mockGames)) // const expectedResults = await getGames() // expect(expectedResults).toEqual(mapGamesData(mockGames.data)) expect(true).toBeTruthy() }) })
jest.config.js
/** @type {import(@jest/types).Config.InitialOptions} */ module.exports = { collectCoverage: true, collectCoverageFrom: [ '<rootDir>/src/**/*.{js,jsx,ts,tsx}', '!**/*.d.ts', '!**/entry.*.*', '!**/node_modules/**', '!**/root.*', '!**/routes/**', '!**/index.*', ], coverageDirectory: '<rootDir>/reports', coverageReporters: ['json', 'lcov', 'text'], coverageThreshold: { global: { branches: 80, functions: 80, lines: 50, statements: 50, }, }, moduleDirectories: ['node_modules', '<rootDir>/node_modules'], setupFilesAfterEnv: ['<rootDir>/jest.setup.js'], testEnvironment: 'jsdom', testPathIgnorePatterns: ['<rootDir>/node_modules/'], transform: { '^.+\\.[jt]sx?$': [ 'babel-jest', { presets: [ '@babel/preset-env', ['@babel/preset-react', { runtime: 'automatic' }], '@babel/preset-typescript', ], plugins: ['@babel/plugin-transform-runtime'], }, ], }, }
jest.setup.js
import '@testing-library/jest-dom/extend-expect' import { installGlobals } from '@remix-run/node' import { configure } from '@testing-library/react' configure({ testIdAttribute: 'data-test' }) installGlobals()
错误截图

解决方案
这个错误是因为babel-jest错误转译了@testing-library/jest-dom扩展的expect方法,导致其内部结构被破坏。可以通过以下步骤解决:
- 添加
transformIgnorePatterns配置
在jest.config.js中新增该配置,排除不需要转译的测试相关依赖包:
module.exports = { // ... 其他配置 transformIgnorePatterns: [ '/node_modules/(?!@testing-library|@remix-run/node|@jest)' ], }
这些包本身已经是编译好的代码,不需要再用babel转译,否则会破坏expect的扩展方法。
- 检查babel配置的
preset-env目标
确保@babel/preset-env的targets适配jest运行环境,可以在babel配置中添加:
{ "presets": [ ["@babel/preset-env", { "targets": { "node": "current" } }], // ... 其他presets ] }
统一依赖版本
检查jest、babel-jest、@babel/preset-env、@testing-library/jest-dom的版本是否兼容,建议升级到最新稳定版,避免版本冲突导致的异常。调整初始化文件导入顺序
将@testing-library/jest-dom/extend-expect的导入放在最顶部,确保它在其他代码之前扩展expect:
import '@testing-library/jest-dom/extend-expect' // 其他导入...
内容的提问来源于stack exchange,提问作者Darrell Washington
相关产品推荐
相关产品推荐

