You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native中Jest/RTL测试元素样式:toHaveProperty匹配器报错排查

问题

我想了解如何在React Native应用中使用Jest/RTL测试特定元素是否具备特定属性,目前我的toHaveProperty匹配器报错,我认为用法有误。

我有一个React Native的Dummy组件如下:

// Dummy.tsx
const Dummy: FC<Props> = ({num, onPressHandler}: Props) => {
  const [state, setState] = useState(false);

  return (
    <View testID="dummy" style={styles.container}>
      <Text>abcdef</Text>
      <Text>{num}</Text>
      <Button title={'Press'} onPress={onPressHandler} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'black',
  },
});

我需要测试testID为"dummy"的View组件是否应用了正确样式,于是在测试文件中编写如下代码:

// Dummy.test.tsx

describe('dummytest', () => {
  test('prop', () => {
    render(<Dummy num={42} onPressHandler={() => {}} />, {});

    const element = screen.getByTestId('dummy');
    expect(element).toHaveProperty('style', {
      flex: 1,
      backgroundColor: 'black',
    });
  });
});

但出现如下错误:

expect(received).toHaveProperty(path, value)

Expected path: "style"
Received path: []

Expected value: {"backgroundColor": "black", "flex": 1}
Received 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": "View", "flags": 0, "index": 0, "key": null, "lanes": 0, "memoizedProps": [Object], "memoizedState": null, "mode": 0, "pendingProps": [Object], "ref": null, "return": [FiberNode], "selfBaseDuration": 0, "sibling": null, "stateNode": [Object], "subtreeFlags": 9439749, "tag": 5, "treeBaseDuration": 0, "type": "View", "updateQueue": null}}

   7 |
   8 |     const element = screen.getByTestId('dummy');
>  9 |     expect(element).toHaveProperty('style', {
     |                     ^
  10 |       flex: 1,
  11 |       backgroundColor: 'black',
  12 |     });

  at Object.toHaveProperty (__tests__/Dummy.test.tsx:9:21)

请问我是否正确使用了toHaveProperty匹配器?

解决方案

你没有正确使用toHaveProperty匹配器,问题出在两个核心点:

  1. RTL返回的元素是React Fiber节点,不是原生组件实例:
    screen.getByTestId('dummy')获取的是React内部的Fiber节点对象,它本身并没有直接的style属性——组件接收的style props存储在Fiber节点的_fiber.memoizedProps或_fiber.pendingProps中。

  2. StyleSheet.create生成的是特殊引用对象,不能直接对比字面量:
    StyleSheet.create会将样式转换为带有内部ID的优化对象,和你写的{flex:1, backgroundColor:'black'}字面量不是同一个引用,直接全等对比会失败。

正确的测试写法

修改测试代码,从Fiber节点的props中获取样式,再用expect.objectContaining做部分匹配(或直接对比预定义的styles.container):

// Dummy.test.tsx
import { styles } from '../Dummy'; // 引入组件中的styles

describe('dummytest', () => {
  test('prop', () => {
    render(<Dummy num={42} onPressHandler={() => {}} />);

    const element = screen.getByTestId('dummy');
    // 从Fiber节点中获取组件接收的props
    const componentProps = element._fiber.memoizedProps;

    // 方法1:直接对比预定义的styles.container(适用于静态样式)
    expect(componentProps.style).toEqual(styles.container);

    // 方法2:部分匹配样式属性(适用于动态合并的样式)
    expect(componentProps.style).toEqual(expect.objectContaining({
      flex: 1,
      backgroundColor: 'black',
    }));
  });
});

为什么之前的写法报错

toHaveProperty('style')尝试在Fiber节点对象上直接查找style属性,但该对象本身没有这个属性,所以报错"Expected path: 'style', Received path: []"。必须深入到_fiber.memoizedProps中才能拿到组件的style props。

内容的提问来源于stack exchange,提问作者adzahari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 02:17:11