使用React Native中的Jest测试在对象上调用的函数

时间:2017-12-13 22:13:06

标签: react-native jestjs enzyme

修改

目前的例子,

  it('CALLED THE canOpenURL FUNCTION', () => {
    const wrapper = mount(<ResourceCardComponent {...mockProps} />);
    const canOpenURLSpy = jest.spyOn(Linking, 'canOpenURL');
    wrapper.find('TouchableOpacity').simulate('click');
    expect(canOpenURLSpy).toHaveBeenCalled();
    canOpenURLSpy.mockReset();
    canOpenURLSpy.mockRestore();
  });

错误

  

expect(jest.fn())。toHaveBeenCalled()期望的模拟函数   被叫了。

问题

我正在使用Jest&amp; Enzyme来测试使用React Native制作的课程。这个类在其中有一个函数,当它被触发时使用链接库来调用canOpenUrlopenUrl。我可以模拟已安装组件上的click事件,但我很难知道我可以实际测试多少。

我的目标是检查Linking.canOpenUrl是否会触发。

〔实施例

组件内部的功能如下所示

  onPressLink() {
    console.log('HEY THIS FUNCTION FIRED WOOT WOOT');
    Linking.canOpenURL(this.props.url).then((supported) => {
      if (supported) {
        Linking.openURL(this.props.url);
      }
    });
  }

我可以像这样模拟这个射击,

describe('onPressLink has been called!', () => {
  it('It clicks the mock function onPressLink!', (done) => {
    const wrapper = mount(<MyComponent {...mockProps} />);
    const onPressLink = jest.fn();
    const a = new onPressLink();
    wrapper.find('TouchableOpacity').first().simulate('click');
    expect(onPressLink).toHaveBeenCalled();
    done();
  });
});

现在确实有效,但我的目标是使用这样的东西,

expect(Linking.canOpenUrl).toHaveBeenCalled();

但我一直收到这个错误,

  

TypeError:无法读取属性&#39; _isMockFunction&#39;未定义的

试图检查此功能是否被触发的当前代码。这是使用模拟方法

单击的父函数内部
  it('calls canOpenURL', () => {
    const wrapper = mount(<MyComponent {...mockProps} />);
    const canOpenURL = jest.spyOn(wrapper.instance, 'onPressLink');
    wrapper.find('TouchableOpacity').simulate('click');
    expect('Linking.canOpenUrl').toHaveBeenCalled();
  });

问题

在执行父函数时,检查Linking.canOpenURL是否被触发的正确方法是什么?

2 个答案:

答案 0 :(得分:2)

(自Jest 19.0.0 +以来)

您可以使用jest.spyOn()监视链接模块方法。

(1)告诉jest窥探模块方法:

const spy = jest.spyOn(Linking, 'canOpenURL');

(2)完成所有测试后,检查间谍:

expect(spy).toHaveBeenCalled();

(3)清理并停止对模块方法进行间谍活动

spy.mockReset();
spy.mockRestore();

如果您不希望测试使用方法的实际实现,您可以像这样伪造它们:

jest.spyOn(Linking, 'canOpenURL').mockImplementation(() => Promise.resolve());

传递给mockImplementation的函数将是调用时方法要做的任何事情。

参考https://facebook.github.io/jest/docs/en/jest-object.html#jestspyonobject-methodname

当使用模块方法的实际实现时,这是异步的,在您测试它时,可能尚未解析该promise。在对其进行任何断言之前,您需要确保在方法实现中解决了任何promise。

解决这个问题的一种方法是使用async / await,如下所示:

it('...', async () => {
  // Wait for promise to resolve before moving on
  await wrapper.instance().onPressLink();

  // make your assertions
  expect(...);
});

另一种选择是使用expect().resolvesavailable since Jest 20.0.0,等待参数中的一些promise,expect()在对该值进行断言之前用值解析。

expect(somePromiseThatEventuallyResolvesWithValue).resolves.toBe(Value);

答案 1 :(得分:0)

我已经用最简单的方法完成了

间谍步骤:

  1. 使用笑话
  2. 使间谍对象具有原始功能
  3. 调用带有/不带有参数的原始函数
  4. 声明应使用有效参数调用的函数
  5. 重置模拟
  6. 还原模拟

这是示例示例

DefaultBrowser.ts 是实际的类。

import { Linking } from 'react-native';

export const openDefaultBrowser = async url => {
  if (await Linking.canOpenURL(url)) {
    Linking.openURL(url);
  }
};

DefaultBrowser.test.ts ,它是测试用例类。

import { openDefaultBrowser } from '../DefaultBrowser';
import { Linking } from 'react-native';

describe('openDefaultBrowser with validate and open url', () => {
  it('validate url', async () => {
    const spy = jest.spyOn(Linking, 'canOpenURL');
    openDefaultBrowser('https://www.google.com');
    expect(spy).toBeCalledWith('https://www.google.com');
    spy.mockReset();
    spy.mockRestore();
  });

  it('open url', async () => {
    const spy = jest.spyOn(Linking, 'openURL');
    openDefaultBrowser('https://www.google.com');
    expect(spy).toBeCalledWith('https://www.google.com');
    spy.mockReset();
    spy.mockRestore();
  });
});

希望这对您有所帮助。