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

wun*_*uno 2 jestjs react-native 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();
  });
Run Code Online (Sandbox Code Playgroud)

错误

expect(jest.fn()).toHaveBeenCalled() 预期的模拟函数已被调用。

问题

我正在使用Jest&Enzyme来测试用React Native. 此类内部有一个函数,该函数在触发时使用链接库调用canOpenUrlopenUrl。我可以模拟已安装组件上的点击事件,但我无法知道我可以实际测试多少。

我的目标是检查是否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);
      }
    });
  }
Run Code Online (Sandbox Code Playgroud)

我可以像这样模拟这次发射,

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();
  });
});
Run Code Online (Sandbox Code Playgroud)

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

expect(Linking.canOpenUrl).toHaveBeenCalled();
Run Code Online (Sandbox Code Playgroud)

但我一直收到这个错误,

类型错误:无法读取未定义的属性“_isMockFunction”

试图检查此函数是否被触发的当前代码。这是在使用模拟方法单击的父函数内,

  it('calls canOpenURL', () => {
    const wrapper = mount(<MyComponent {...mockProps} />);
    const canOpenURL = jest.spyOn(wrapper.instance, 'onPressLink');
    wrapper.find('TouchableOpacity').simulate('click');
    expect('Linking.canOpenUrl').toHaveBeenCalled();
  });
Run Code Online (Sandbox Code Playgroud)

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

nbk*_*ope 5

(自 Jest 19.0.0+ 起)

您可以使用jest.spyOn().

(1) 告诉 jest 监视模块方法:

const spy = jest.spyOn(Linking, 'canOpenURL');
Run Code Online (Sandbox Code Playgroud)

(2) 做完所有需要测试的事情后,检查spy:

expect(spy).toHaveBeenCalled();
Run Code Online (Sandbox Code Playgroud)

(3)清理并停止窥探模块方法

spy.mockReset();
spy.mockRestore();
Run Code Online (Sandbox Code Playgroud)

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

jest.spyOn(Linking, 'canOpenURL').mockImplementation(() => Promise.resolve());
Run Code Online (Sandbox Code Playgroud)

传递给 mockImplementation 的函数将是您希望该方法在调用时执行的任何操作。

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


当使用模块方法的实际实现时,它是异步的,在您测试它时可能还没有解决承诺。在对其进行任何断言之前,您需要确保在您的方法实现中解决了任何承诺。

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

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

  // make your assertions
  expect(...);
});
Run Code Online (Sandbox Code Playgroud)

另一种选择是使用expect().resolves自 Jest 20.0.0 起可用,在对那个值进行断言之前,您等待 expect() 参数中的一些承诺以一个值解析。

expect(somePromiseThatEventuallyResolvesWithValue).resolves.toBe(Value);
Run Code Online (Sandbox Code Playgroud)