我使用 react native 和 jest 来创建我的测试。我在测试侦听来自 expo-linking 的 url 事件的事件侦听器时遇到了问题。此事件侦听器位于 useEffect 钩子内。
下面是我的自定义钩子的代码,里面有我的 useEffect 和一个事件监听器:
useEffect(() => {
isMounted.current = true;
Linking.addEventListener('url', async () => {
try {
if (!navigation.isFocused() || !isMounted.current) return;
setIsLoading(true);
const response = await api.get('sessions/auth/success');
if (!response.data) return;
console.log('aqui');
const { notRegisteredUser, token } = response.data;
api.defaults.headers.authorization = `Bearer ${token}`;
if (notRegisteredUser && token) {
setIsLoading(false);
navigation.navigate('BirthDateScreen');
dispatch(
updateUser({
...notRegisteredUser,
}),
);
}
} catch (err) {
Alert.alert('Error', `${translate('loginRegisterError')}: `, err);
}
});
return () => {
isMounted.current = false;
};
}, [dispatch, navigation]);
在我的测试文件中,我有以下模拟:
jest.mock('expo-linking', () => {
return {
addEventListener: (event: string, callback: () => void) => callback(),
};
});
jest.mock('@react-navigation/native', () => {
return {
useNavigation: () => ({
isFocused: mockedNavigationFocus,
navigate: mockedNavigation,
}),
};
});
jest.mock('react-redux', () => {
return {
useDispatch: jest.fn(),
};
});
jest.mock('../../../store/modules/user/actions', () => {
return {
updateUser: jest.fn(),
};
});
jest.mock('i18n-js', () => {
return {
locale: 'en',
t: () => 'any key',
};
});
最后,这是我第一次尝试时的测试结果:
it('should pass the test', async done => {
mockedNavigationFocus.mockImplementation(() => true);
apiMock.onGet('sessions/auth/success').reply(200, {
notRegisteredUser: { name: 'Logan' },
token: '123',
});
render(<LoginScreen />);
await waitFor(() =>
expect(mockedNavigation).toHaveBeenCalledWith('BirthDateScreen'),
);
done();
});
在我的第二次尝试中,这是我的测试的样子(我使用了来自 @testing-library/react-hooks 的 renderHooks):
it('should pass the test', async () => {
mockedNavigationFocus.mockImplementation(() => true);
apiMock.onGet('sessions/auth/success').reply(200, {
notRegisteredUser: { name: 'Logan' },
token: '123',
});
const { result, waitForValueToChange } = renderHook(() => useLoginButton());
const { isLoading } = result.current;
await waitForValueToChange(() => isLoading);
await waitForValueToChange(() => isLoading);
expect(mockedNavigation).toHaveBeenCalledWith('BirthDateScreen');
});
通过这两个测试,我得到以下错误: test error
我得到的另一个错误是我的 useEffect 中的回调函数在它停止之前运行了很多次,而这在我不测试时不会发生。
有谁知道我该如何编写这个测试?