React Native自定义Text组件单元测试报错:需HTMLElement/SVGElement
React Native(Expo)NativeWind封装Text组件的单元测试问题
问题描述
作为React Native(Expo)和单元测试新手,我在测试基于NativeWind封装的自定义Text组件样式时遇到问题:使用toHaveStyle断言字体大小时,报错提示接收值必须是HTMLElement或SVGElement,但实际拿到的是React Fiber对象,即便引入@testing-library/jest-native扩展也无法解决。
自定义组件代码
import { styled } from 'nativewind'; import React from 'react'; import type { TextProps } from 'react-native'; import { StyleSheet, Text as NNText } from 'react-native'; const SText = styled(NNText); export interface CustomTextProps extends TextProps { variant?: keyof typeof textVariants; className?: string; } export const textVariants = { //..... }; export const Text = ({ variant = 'md', className = '', style, children, ...props }: CustomTextProps) => { return ( <SText className={` ${textVariants[variant]} ${className} `} style={StyleSheet.flatten([ { writingDirection: isRTL ? 'rtl' : 'ltr' }, style, ])} {...props} > {children} </SText> ); };
测试代码
import '@testing-library/jest-native/extend-expect'; import { render, screen } from '@testing-library/react-native'; import { CustomTextProps, Text } from '../text'; describe('text component', () => { const renderComponent = (props: CustomTextProps) => render(<Text {...props} />); it('should accept variant and className props', async () => { renderComponent({ variant: 'xs', className: 'bg-primary-50', children: 'tested text', }); const text = screen.getByText('tested text'); expect(text).toBeTruthy(); expect(text).toHaveStyle({ fontSize: 16 }); // 报错位置 }); });
报错信息
expect(received).toHaveStyle() received value must be an HTMLElement or an SVGElement. Received has type: object Received has value: {"_fiber": {"_debugHookTypes": null, "_debugNeedsRemount": false, "_debugOwner": [FiberNode], "_debugSource": null, "actualDuration": 0, "actualStartTime": -1, "alternate": null, "child": [FiberNode], "childLanes": 0, "deletions": null, "dependencies": null, "elementType": [Function Component], "flags": 1, "index": 0, "key": null, "lanes": 0, "memoizedProps": [Object], "memoizedState": null, "mode": 0, "pendingProps": [Object], "ref": null, "return": [FiberNode], "selfBaseDuration": 0, "sibling": null, "stateNode": [Component], "subtreeFlags": 0, "tag": 1, "treeBaseDuration": 0, "type": [Function Component], "updateQueue": [Object]}} 18 | expect(text).toBeTruthy(); 19 | > 20 | expect(text).toHaveStyle({ fontSize: 16 }); | ^ 21 | }); 22 | }); 23 | at __EXTERNAL_MATCHER_TRAP__ (node_modules/expect/build/index.js:342:30) at Object.toHaveStyle (node_modules/expect/build/index.js:343:15) at Object.<anonymous> (src/ui/core/__test__/text.test.tsx:20:18) at asyncGeneratorStep (node_modules/@babel/runtime/helpers/asyncToGenerator.js:3:24) at _next (node_modules/@babel/runtime/helpers/asyncToGenerator.js:22:9) at node_modules/@babel/runtime/helpers/asyncToGenerator.js:27:7 at tryCallTwo (node_modules/promise/lib/core.js:45:5) at doResolve (node_modules/promise/lib/core.js:200:13) at new Promise (node_modules/promise/lib/core.js:66:3)
解决方案
1. 配置NativeWind Jest预设
NativeWind需要在测试环境中配置专门的预设来解析Tailwind样式,在jest.config.js中添加:
module.exports = { preset: 'nativewind/jest', // 保留你现有的其他Jest配置 };
2. 确保使用RN测试库的匹配器
@testing-library/jest-native的toHaveStyle是为RN组件设计的,但需要确保测试对象是RN组件实例。可以给组件添加testID来精准获取:
修改测试代码:
import '@testing-library/jest-native/extend-expect'; import { render, screen } from '@testing-library/react-native'; import { CustomTextProps, Text } from '../text'; describe('text component', () => { const renderComponent = (props: CustomTextProps) => render(<Text {...props} />); it('should apply correct styles for variant', async () => { renderComponent({ variant: 'xs', className: 'bg-primary-50', children: 'tested text', testID: 'custom-text-component' // 添加testID }); const textComponent = screen.getByTestId('custom-text-component'); expect(textComponent).toBeTruthy(); // 使用jest-native的toHaveStyle断言 expect(textComponent).toHaveStyle({ fontSize: 16 }); }); });
3. 备选:直接断言组件样式属性
如果toHaveStyle仍不生效,可以直接检查组件的props.style,或者验证是否应用了正确的variant类:
// 方式1:断言style属性 expect(textComponent.props.style).toContainEqual({ fontSize: 16 }); // 方式2:验证className是否包含对应variant的样式类 import { textVariants } from '../text'; expect(textComponent.props.className).toContain(textVariants.xs);
4. 检查版本兼容性
确保@testing-library/react-native、@testing-library/jest-native和nativewind版本互相兼容,比如NativeWind v4需要搭配较新的测试库版本,建议参考官方文档确认版本匹配。
内容的提问来源于stack exchange,提问作者Rabeb bahry
相关产品推荐
相关产品推荐

