【问题标题】:React Native Test Button PressReact Native 测试按钮按下
【发布时间】:2019-03-18 11:45:49
【问题描述】:

我正在尝试测试从 React Native Button 元素调用组件方法。

由于某种原因,除非我同时做这两件事,否则测试会失败。

wrapper.find(Button).first().props().onPress();
wrapper.find(Button).first().simulate('press');

如果我注释掉其中任何一行,测试就会失败,表明 expect(instance.toggleEmailPasswordModal).toHaveBeenCalled(); 失败。

这是我的组件:

import React, { Component } from 'react';
import { Button, SafeAreaView, Text } from 'react-native';

import EmailPasswordModal from './EmailPasswordModal/EmailPasswordModal';

class Login extends Component {
  state = {
    emailPasswordModalVisible: false,
  };

  toggleEmailPasswordModal = () => {
    console.log('TOGGLED!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
    const { emailPasswordModalVisible } = this.state;
    this.setState({ emailPasswordModalVisible: !emailPasswordModalVisible });
  };

  render() {
    const { emailPasswordModalVisible } = this.state;
    return (
      <SafeAreaView>

        <EmailPasswordModal
          visible={ emailPasswordModalVisible }
          close={ this.toggleEmailPasswordModal }
        />

        <Text>Login Screen!</Text>

        <Button
          onPress={ this.toggleEmailPasswordModal }
          title="Login with Email and Password"
          color="#841584"
          accessibilityLabel="Login with Email and Password"
        />

      </SafeAreaView>
    );
  }
}

export default Login;

这是我的测试:

import React from 'react';
import ShallowRenderer from 'react-test-renderer/shallow';
import { shallow } from 'enzyme';
import { Button } from 'react-native';

import Login from './Login';

describe('Login Screen', () => {
  describe('Snapshot Tests', () => {
    it('renders the screen with default state', () => {
      const renderer = new ShallowRenderer();
      const props = {};

      renderer.render(<Login { ...props } />);
      expect(renderer.getRenderOutput()).toMatchSnapshot();
    });
  });

  describe('Functional Tests', () => {
    it('calls the toggleEmailPasswordModal method', () => {
      const wrapper = shallow(<Login />);
      const instance = wrapper.instance();
      jest.spyOn(instance, 'toggleEmailPasswordModal');
      wrapper.find(Button).first().props().onPress();
      wrapper.find(Button).first().simulate('press');
      expect(instance.toggleEmailPasswordModal).toHaveBeenCalled();
    });
  });
});

奇怪的是,当测试运行时,输出显示“TOGGLED!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!”两次因为组件中的日志记录。

但是,如果我将 expect 更改为:

expect(instance.toggleEmailPasswordModal).toHaveBeenCalledTimes(1);

测试通过。

如果我将expect 更改为:

expect(instance.toggleEmailPasswordModal).toHaveBeenCalledTimes(2);

测试失败,说 toggleEmailPasswordModal 只被调用了 1 次。

为什么我需要这两条wrapper.find(Button)... 行?我从未见过任何其他测试都需要它们。

谢谢, 贾斯汀

更新:

我更新了我的测试如下:

it('calls the toggleEmailPasswordModal method', () => {
  const wrapper = shallow(<Login />);
  const instance = wrapper.instance();
  jest.spyOn(instance, 'toggleEmailPasswordModal');
  wrapper.find(Button).first().props().onPress();
  wrapper.find(Button).first().simulate('press');
  expect(instance.toggleEmailPasswordModal).toHaveBeenCalled();

  // I ADDED THIS SECTION HERE
  expect(instance.state.emailPasswordModalVisible).toBe(true);
});

测试失败,因为instance.state.emailPasswordModalVisible = false。这很奇怪,因为显然调用了 toggleEmailPasswordModal。但是,由于我怀疑它实际上被调用了两次,所以我将测试更新如下:

it('calls the toggleEmailPasswordModal method', () => {
  const wrapper = shallow(<Login />);
  const instance = wrapper.instance();
  jest.spyOn(instance, 'toggleEmailPasswordModal');
  wrapper.find(Button).first().props().onPress();

  // CHANGES START HERE
  // wrapper.find(Button).first().simulate('press');
  // expect(instance.toggleEmailPasswordModal).toHaveBeenCalled();
  expect(instance.state.emailPasswordModalVisible).toBe(true);
});

你猜怎么着?测试正常通过。所以很明显,两次调用wrapper.find... 函数实际上就是两次调用toggleEmailPasswordModal 方法。那么,如果我不调用两次,为什么它无法检测到它?为什么它错误地认为该方法只被调用过一次?

【问题讨论】:

    标签: react-native jestjs


    【解决方案1】:

    我终于有了答案。根据Jest spyOn function called,我需要做instance.forceUpdate() 将间谍附加到组件。

    it('calls the toggleEmailPasswordModal method', () => {
      const wrapper = shallow(<Login />);
      const instance = wrapper.instance();
      const spy = jest.spyOn(instance, 'toggleEmailPasswordModal');
    
      // This is added per https://stackoverflow.com/questions/44769404/jest-spyon-function-called/44778519#44778519
      instance.forceUpdate();
      wrapper.find(Button).first().props().onPress();
    
      expect(spy).toHaveBeenCalledTimes(1);
      expect(instance.state.emailPasswordModalVisible).toBe(true);
    });
    

    现在,测试通过了!

    【讨论】:

      猜你喜欢
      • 2018-08-18
      • 2021-12-23
      • 1970-01-01
      • 1970-01-01
      • 2021-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-30
      相关资源
      最近更新 更多