【问题标题】:How to unit test PanResponder in React Native?如何在 React Native 中对 PanResponder 进行单元测试?
【发布时间】:2017-12-17 09:22:05
【问题描述】:

我正在开发一个通过 PanResponder 处理手势的 React Native 组件。

我想测试当某些 dxdy 值传递给onPanResponderRelease 方法时,会执行预期的操作。请在下面找到我想测试的示例:

export default class MyComponent extends Component<Props, State> {
  constructor(props: Props) {
    super(props);
    this._panResponder = this._initPanResponder();
  }

  _initPanResponder(): PanResponder {
    const panResponder = PanResponder.create({
      onStartShouldSetPanResponder: () => true,
      onMoveShouldSetPanResponder: () => true,
      onPanResponderMove: Animated.event([
        null,
        { dx: this._animation.x, dy: this._animation.y }
      ]),
      onPanResponderRelease: (e, gestureState) => {
        const { dx, dy } = gestureState;

        if (dy > 100) {
          doSomething(); // <---- what I would like to unit test
        }
      }
    });
    return panResponder;
  }
}

是否有任何直接的方法可以使用 Jest 对以下内容进行单元测试?

【问题讨论】:

    标签: unit-testing react-native jestjs


    【解决方案1】:

    我倾向于不测试接线代码,因为测试一个实际的 PanResponder 涉及一个 UI 测试,该测试很难编写,通常是不稳定的,并且没有什么价值。

    你能做的,就是把事件处理函数提取出来,独立测试一下。

    在这种情况下,测试将非常简单,因为您需要做的就是调用测试中的处理程序并查看您是否得到了预期的结果。

    【讨论】:

    • 谢谢,有道理!我以某种方式希望有一种模拟手势的方法。但正如你所说,我不确定它会带来多少价值(尤其是在单元测试的范围内)。我看到的唯一缺点是我必须导出该事件处理函数(虽然以前没有)才能直接从测试中调用它。
    • 你能告诉我怎么做吗?
    【解决方案2】:

    如果您想测试用户与组件的交互,您应该模拟PanResponder,将作为参数提供给PanResponder.create 的函数转发给它返回的panHandlers

    // setup-tests.ts
    
    jest.doMock('react-native', () => {
      return Object.setPrototypeOf(
          PanResponder: {
            ...ReactNative.PanResponder,
            create: (config: any) => ({ panHandlers: config }),
          },
        },
        ReactNative
      );
    });
    

    这样,当你在处理 Pan 的 View 中传播 panHandlers 时,你可以按照你在文件中设置的方式访问函数

    // pan-handling-component.tsx
    
    const Component: React.FC = () => {
    ...
    
      const panResponder = React.useRef(
          PanResponder.create({
            ...
            onPanResponderMove: (_, gestureState) => {
              Animated.event([slideAnim], { useNativeDriver: false })(
                gestureState.moveY
              );
            },
            onPanResponderTerminationRequest: () => true,
            onPanResponderRelease: () => {
              // @ts-ignore
              const currentValue = slideAnim._value;
    
              if (currentValue < 0) {
                slideIn();
              } else if (currentValue > height - 300) {
                handleClose();
              }
            },
          })
        ).current;
    
    ...
    
        return (
    
          <View
             testID={DRAWER_WRAPPER_TESTID}
             {...panResponder.panHandlers}
          > 
            ...
          </View>
    
        );
    
    
    

    最后,单元测试应该是这样的

    // pan-handling-component.test.tsx
    
    ...
    
        const panHandler = instance.root.findByProps({
          testID: DRAWER_WRAPPER_TESTID,
        });
    
        act(() => {
          panHandler.props.onPanResponderMove(eventMock, gestureStateMOck);
          panHandler.props.onPanResponderRelease();
        });
    
    
    ...
    

    【讨论】:

      猜你喜欢
      • 2020-07-24
      • 1970-01-01
      • 2016-11-12
      • 1970-01-01
      • 2021-11-21
      • 1970-01-01
      • 2020-08-17
      • 2018-02-07
      • 2021-10-07
      相关资源
      最近更新 更多