【问题标题】:Mock Linking.openURL in React Native it's never been called在 React Native 中模拟 Linking.openURL 它从未被调用过
【发布时间】:2021-08-31 19:46:28
【问题描述】:

我正在为我的应用程序编写一些测试,并且我正在尝试模拟 Linking 模块。我正在使用jestLinking.canOpenURL 模拟它工作正常(toHaveBeenCalled 正在返回 true),但永远不会调用 openURL 模拟。

    function mockSuccessLinking() {
      const canOpenURL = jest
        .spyOn(Linking, 'canOpenURL')
        .mockImplementation(() => Promise.resolve(true));
      const openURL = jest
        .spyOn(Linking, 'openURL')
        .mockImplementation(() => Promise.resolve(true));

      return { canOpenURL, openURL };
    }

问题是openURL没有被调用。

这是测试:

test('should open url when there is a proper app the open it', async () => {
      const { canOpenURL, openURL } = mockSuccessLinking();
      const { result } = renderHook(() =>
         useApplyToJob('https://www.google.com/'),
      );
      const [apply] = result.current;

      // Act
      apply();

      // Assert
      expect(result.current[1].error).toBeNull();
      expect(canOpenURL).toHaveBeenCalled();
      expect(openURL).toHaveBeenCalled();
});

这是正在测试的钩子:

export function useApplyToJob(url) {
  const [error, setError] = useState(null);

  const apply = () => {
    Linking.canOpenURL(url).then(supported => {
      if (supported) {
        Linking.openURL(url);
      } else {
        setError(`Don't know how to open ${url}`);
      }
    });
  };

  return [apply, { error }];
}

【问题讨论】:

    标签: react-native jestjs react-hooks react-hooks-testing-library


    【解决方案1】:

    鉴于canOpenURL 返回一个promise,您需要等待异步发生,然后再测试openURL 是否已被调用。 react-hooks-testing-library 发送了一些 async utils 来帮助解决这个问题。

    通常最好使用waitForNextUpdatewaitForValueToChange,因为它们更能描述测试正在等待的内容,但是您的钩子在成功的情况下不会更新任何状态,因此您需要使用更通用的waitFor 实用程序:

    test('should open url when there is a proper app the open it', async () => {
          const { canOpenURL, openURL } = mockSuccessLinking();
          const { result, waitFor } = renderHook(() =>
             useApplyToJob('https://www.google.com/'),
          );
          const [apply] = result.current;
    
          // Act
          apply();
    
          // Assert
          expect(result.current[1].error).toBeNull();
          expect(canOpenURL).toHaveBeenCalled();
    
          await waitFor(() => {
              expect(openURL).toHaveBeenCalled();
          });
    });
    

    附带说明,不建议将result.current 解构以访问apply。它现在可能可以工作,但在您调用的 apply 使用先前渲染中的陈旧值之前不需要进行太多重构。

    同样,我建议将apply() 调用包装在act 中,即使它现在不更新任何状态。它只是使将来的重构更容易,并在您测试错误案例时使您的测试更加一致(这需要act 调用)。

    import { renderHook, act } from '@testing-library/react-hooks';
    
    // ...
    
    test('should open url when there is a proper app the open it', async () => {
          const { canOpenURL, openURL } = mockSuccessLinking();
          const { result, waitFor } = renderHook(() =>
             useApplyToJob('https://www.google.com/'),
          );
    
          // Act
          act(() => {
            result.current[0]();
          });
    
          // Assert
          expect(result.current[1].error).toBeNull();
          expect(canOpenURL).toHaveBeenCalled();
    
          await waitFor(() => {
              expect(openURL).toHaveBeenCalled();
          });
    });
    

    【讨论】:

    • 非常感谢。我现在工作正常!
    猜你喜欢
    • 2017-11-18
    • 2019-03-02
    • 2017-12-15
    • 1970-01-01
    • 2021-09-12
    • 1970-01-01
    • 2019-07-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多