【问题标题】:How to test a button click in React with TypeScript, Jest and Enzyme如何使用 TypeScript、Jest 和 Enzyme 在 React 中测试按钮点击
【发布时间】:2018-10-08 10:14:03
【问题描述】:

我正在使用 TypeScript 构建一个 React Native 应用程序。我正在使用 Jest 和 Enzyme 进行组件测试。我也在使用 React Navigation

我正在努力编写用于单击我的按钮的单元测试。

这是组件的代码(只是渲染函数):

  render() {
    const { navigation } = this.props;
    return (
      <View style={styles.container}>
        <Button
          raised
          title={strings.painButtonTitle}
          buttonStyle={styles.painButton}
          titleStyle={styles.title}
          onPress={() => navigation.navigate("QuestionsScreen")}
        />
      </View>
    );
  }

现在是单元测试。

  describe("interaction", () => {
    let wrapper: ShallowWrapper;
    let props: Props;
    beforeEach(() => {
      props = createTestProps({});
      wrapper = shallow(<HomeScreen {...props} />);
    });

    describe("clicking the Pain Button", () => {
      it("should navigate to the 'QuestionsScreen'", () => {
        wrapper.find("Button").simulate("click");

        expect(props.navigation.navigate).toHaveBeenCalledTimes(1);
      });
    });
  });

这会失败并声称 navigation.navigate 函数 - 使用 jest.fn() 模拟 - 从未被调用。

我认为这与为按钮提供错误功能有关。问题是,我不能不这样做,因为我需要使用参数"QuestionsScreen" 进行调用。所以我不能做类似onPress={this.navigation.navigate) 的事情,然后奇迹般地打电话给"QuestionsScreen",可以吗?

我怎样才能让这个测试通过?

【问题讨论】:

    标签: typescript react-native jestjs react-navigation enzyme


    【解决方案1】:

    "Common Gotchas" section for simulate 表示“尽管名称暗示这模拟了一个实际事件,但 .simulate() 实际上会根据你给它的事件定位组件的 prop。例如, .simulate('click' ) 实际上会获取 onClick 属性并调用它。”

    这种行为可以在Enzyme 源代码herehere 中看到。

    所以wrapper.find("Button").simulate("click"); 行最终尝试调用不存在的ButtononClick 属性,因此它基本上什么都不做。

    Airbnb 开发人员的This post 建议直接调用道具并避免使用simulate

    这是一个修改后的测试,直接调用 onPress 属性:

    it("should navigate to the 'QuestionsScreen'", () => {
      wrapper.find(Button).props().onPress({} as any);
    
      expect(props.navigation.navigate).toHaveBeenCalledTimes(1);   // SUCCESS
    });
    

    【讨论】:

    • 我只有一个问题:我收到错误:Property 'onPress' does not exist on type 'HTMLAttributes'. 我该如何解决?这就是我定义包装器的方式:let wrapper: ShallowWrapper&lt;{}, {}, HomeScreen&gt;; 然后wrapper = shallow(&lt;HomeScreen {...props} /&gt;);
    • 我也试过wrapper.find("Button").prop("onPress")({} as any);,它给出了错误:Cannot invoke an expression whose type lacks a call signature. Type '{}' has no compatible call signatures.
    • 另一个更新:现在我导入了 Button 并逐字执行了您所写的操作:wrapper .find(Button) .props() .onPress({} as any); - 没有在 Button 周围加上引号。然后我得到错误:Cannot invoke an object which is possibly 'undefined'.
    • 为此提出了一个新的stackoverflow问题:stackoverflow.com/questions/52697779/…
    • 哦,是的,我应该指出我直接使用了Button,以便可以推断道具的类型
    【解决方案2】:

    我和你有一个类似的问题。我尝试了simulate("click"),但失败了,因为该组件没有onClick 属性。

    我的方法是将测试用例更改为wrapper.find("form").simulate("submit"),因为我的导航功能是在表单的提交属性中定义的。

    【讨论】:

      猜你喜欢
      • 2018-10-31
      • 2017-04-13
      • 2017-11-26
      • 2021-02-14
      • 2017-11-10
      • 2018-10-20
      • 2020-08-07
      • 1970-01-01
      • 2017-07-24
      相关资源
      最近更新 更多