在 React Native 中模拟 Linking.openURL 它从未被调用过
Mock Linking.openURL in React Native it's never been called
我正在为我的应用编写一些测试,我正在尝试模拟 Linking
模块。我正在使用 jest
。
Linking.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 }];
}
给定 canOpenURL
returns 承诺,您需要等待异步发生,然后再测试 openURL
是否已被调用。 react-hooks-testing-library
发布了一些 async utils 来帮助解决这个问题。
通常最好使用 waitForNextUpdate
或 waitForValueToChange
因为它们更能描述测试正在等待什么,但是在成功的情况下你的钩子不会更新任何状态,所以您将需要改用更通用的 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();
});
});
我正在为我的应用编写一些测试,我正在尝试模拟 Linking
模块。我正在使用 jest
。
Linking.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 }];
}
给定 canOpenURL
returns 承诺,您需要等待异步发生,然后再测试 openURL
是否已被调用。 react-hooks-testing-library
发布了一些 async utils 来帮助解决这个问题。
通常最好使用 waitForNextUpdate
或 waitForValueToChange
因为它们更能描述测试正在等待什么,但是在成功的情况下你的钩子不会更新任何状态,所以您将需要改用更通用的 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();
});
});