我应该如何在 React Native 中的 Expo 应用程序的 Jest 中测试 useAuth0().authorize

问题描述 投票:0回答:1

我四处寻找答案,但找不到有关此主题的任何解决方案。

本质上,我正在尝试使用“@testing-library/react-native”编写一些单元测试来测试按下登录按钮是否会调用 useAuth0().authorize 。我预计它已被调用 1 次,但收到 0 次回电。

我做错了什么?

以下是 ./app/(login)/index.tsx 中的登陆页面:

import { StyleSheet, TouchableOpacity, SafeAreaView } from 'react-native';
import { useAuth0 } from 'react-native-auth0';

export default function Landing(): React.JSX.Element {
  const { authorize, clearSession, user } = useAuth0();

  const onLogin = async () => {
    try {
      await authorize();
    } catch (e) {
      console.log(e);
    }
  };

  const loggedIn = user !== undefined && user !== null;

  const onLogout = async () => {
    try {
      await clearSession();
    } catch (e) {
      console.log('Log out cancelled');
    }
  };

  return (
    <SafeAreaView style={styles.container}>
      <TouchableOpacity style={styles.logBtn} onPress={loggedIn ? onLogout : onLogin} testID='loginBtn'>
        {user && <Text style={styles.btnTxt}>Log Out</Text>}
        {!user && <Text style={styles.btnTxt}>Log In</Text>}
      </TouchableOpacity>
    </SafeAreaView>
}

这是我进行的测试:

import { render, fireEvent, waitFor } from '@testing-library/react-native';
import { useAuth0 } from 'react-native-auth0';
import Landing from '@/app/(login)/index';


jest.mock('react-native-auth0', () => ({
  useAuth0: jest.fn(() => ({
    authorize: jest.fn(),
  })),
}));

describe('Login page renders and performs correct actions through Auth0', () => {
  test('Login button correctly calls authorize function', async () => {
     const { getByTestId } = render(<Landing />);
     const loginBtn = getByTestId('loginBtn');
      
     fireEvent.press(loginBtn)

     await waitFor(() => {
       expect(useAuth0().authorize).toHaveBeenCalledTimes(1);
     })
  })
})

这是我收到的错误:

expect(jest.fn()).toHaveBeenCalledTimes(expected)

    Expected number of calls: 1
    Received number of calls: 0

      43 |       fireEvent.press(loginBtn)
      44 |
    > 45 |       await waitFor(() => {
         |                    ^
      46 |         expect(useAuth0().authorize).toHaveBeenCalledTimes(1);
      47 |       })
      48 |     })

我尝试过的其他一些事情:

切换:

fireEvent.press(loginBtn);
fireEvent(loginBtn, 'click');

<TouchableOpacity></TouchableOpacity>
<Button></Button>

这些也不起作用:(

typescript react-native jestjs expo react-native-auth0
1个回答
0
投票

这里的问题是,您在测试中引用了一个新的模拟,而不是在组件中引用的模拟。

要使其正常工作,您将需要使用传递到模拟模块中的模拟函数。

例如,我使用 React Router 的

useNavigate
钩子处理过一个非常相似的场景:

const mockUseNavigate = jest.fn();

jest.mock("react-router", () => ({
  ...jest.requireActual("react-router"),
  useNavigate: () => mockUseNavigate,
}));

然后可以通过以下两种方式之一使用它:

const useNavigateMock = useNavigate();
// do stuff to trigger the nav
expect(useNavigateMock).toHaveBeenCalledWith("/");

或者你可以直接使用模拟:

expect(mockUseNavigate).toHaveBeenCalledWith("/");

第一种方法的缺点是您需要在每个测试中导入并调用钩子,第二种方法的缺点是您使用在测试/描述范围之外定义的模拟。无论您使用哪种方法,重要的是您最终都会得到

beforeEach
来重置模拟或在 Jest 配置中设置
resetMocks: true

在您的情况下,您当然可以更新您的

useAuth0()

 模拟以返回一个对象以匹配钩子返回值的形状。例如

const mockAuthorize = jest.fn(); jest.mock('react-native-auth0', () => ({ useAuth0: () => ({ authorize: mockAuthorize, }), }));
(我也删除了包装

jest.fn()

,因为你可能不需要它,除非你断言钩子本身的使用)

© www.soinside.com 2019 - 2024. All rights reserved.