React Native升级后测试随机报错:'render' method has not been called
测试随机失败问题排查:
'render' method has not been called 环境信息
项目依赖
"jest-environment-jsdom": "29.7.0", "jest-expo": "49.0.0",
开发依赖
"@testing-library/jest-native": "5.4.3", "@testing-library/react-hooks": "8.0.1", "@testing-library/react-native": "12.3.0", "jest": "29.7.0", "ts-jest": "29.1.1",
Jest配置(jest.config.js)
module.exports = { testEnvironment: 'node', setupFiles: [ './jest.setup.js', './node_modules/react-native-gesture-handler/jestSetup.js', './node_modules/react-native/jest/setup.js', './node_modules/react-native/Libraries/Utilities/__mocks__/BackHandler.js', ], transform: { '^.+\\.tsx?$': [ 'ts-jest', { tsconfig: 'tsconfig.jest.json', babelConfig: true, diagnostics: { exclude: ['**'], }, }, ], }, preset: 'jest-expo', setupFilesAfterEnv: ['@testing-library/jest-native/extend-expect'], moduleFileExtensions: ['js', 'json', 'node', 'ts', 'tsx'], moduleNameMapper: { '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/assetsTransformer.js', '\\.(css|less)$': '/assetsTransformer.js', '\\.svg': '<rootDir>/__mocks__/svgMocks.js', 'uuid': require.resolve('uuid'), }, transformIgnorePatterns: [ 'node_modules/(?!(jest-)?@react-native|react-native|@react-native-community|@react-navigation|expo(nent)?|@expo(nent)?/.*)', ], roots: ['<rootDir>/__mocks__', '<rootDir>/src'], collectCoverageFrom: [ '!src/core/**/**.js', '!src/api', '!src/constants', '!src/navigation', '!node_modules/', '!src/index.js', 'src/**/*.{js,jsx,ts,tsx}', '!src/**/stories.{js,jsx,ts,tsx}', '!src/**/styles.{js,jsx,ts,tsx}', '!src/**/types.{js,jsx,ts,tsx}', ], coverageThreshold: { global: { branches: 30, functions: 30, lines: 30, statements: 30, }, }, };
自定义render封装
import React, { ReactElement } from 'react'; import { render, act } from '@testing-library/react-native'; import configureStore from 'redux-mock-store'; import AppProviders from 'core/providers'; import { RootState } from 'core/store'; type Props = { initialState?: Partial<RootState>; hideGlobalConfirm?: boolean; mockStore?: boolean; }; const middlewares: any = []; const mockStore = configureStore(middlewares); const customRender = (ui: ReactElement, options?: Omit<any, 'queries'> & Props) => render(ui, { wrapper: ({ children }) => { if (options?.mockStore) { const store = mockStore(options?.initialState); return ( <AppProviders store={store} hideGlobalConfirm={options?.hideGlobalConfirm}> {children} </AppProviders> ); } return ( <AppProviders initialState={options?.initialState as any} hideGlobalConfirm={options?.hideGlobalConfirm}> {children} </AppProviders> ); }, ...options, }); export async function wait(ms = 1000) { await act(async () => { return new Promise((resolve) => { setTimeout(resolve, ms); }); }); } export * from '@testing-library/react-native'; export { customRender };
问题描述
将React Native升级至0.72.4并同步更新测试库后,测试出现随机失败,报错信息为'render' method has not been called,每次失败的测试用例不固定。例如以下用例曾出现失败:
describe('renders correctly', () => { it('should be able to render - default', async () => { const wrapper = customRender(renderComponent()); const myComponent = await wrapper.findByTestId('myComponent'); expect(myComponent).toBeDefined(); expect(wrapper.toJSON()).toMatchSnapshot(); }); });
升级前所有测试均正常运行。
可能原因分析
- 测试环境冲突:jest配置中同时设置了
testEnvironment: 'node'和preset: 'jest-expo',jest-expo本身会指定测试环境,双重设置可能导致环境初始化不稳定,引发随机渲染问题。 - setupFiles加载顺序不合理:setupFiles数组中自定义的
jest.setup.js优先于react-native/jest/setup.js加载,可能导致React Native核心mock未就绪,触发渲染异常。 - 自定义render未处理异步初始化:部分组件包含Redux store初始化、异步请求等异步逻辑,自定义render直接返回未等待这些操作完成,导致查询组件时渲染未完成。
- 测试库版本兼容性问题:@testing-library/react-native 12.3.0与RN 0.72、Expo 49的组合可能存在适配问题,异步渲染的内部逻辑未匹配新版本RN的机制。
- 测试状态未重置:测试用例之间的Redux store、第三方模块mock未正确重置,状态污染导致后续测试的渲染上下文异常。
- 转译配置不全:升级后新增的依赖可能未被纳入
transformIgnorePatterns的白名单,未转译的代码在测试环境中运行出错,引发随机失败。
内容的提问来源于stack exchange,提问作者Rameez Hussain
相关产品推荐
相关产品推荐

