我想用Jest在React Native中模拟node_module'React Native Keychain'。
在docs之后,我创建了一个名为__mocks__
的文件夹,并在其中创建了一个名为react-native-keychain.js
的文件。
这是文件中的代码:
export default jest.mock("react-native-keychain", () => {
const token = "abcdefghijklmnopqrstuvwxyz0123456789";
const credentials = {
username: "session",
password: token
};
return {
setGenericPassword: jest.fn(
(username, password) => new Promise((resolve, reject) => resolve(true)) // eslint-disable-line no-unused-vars
),
getGenericPassword: jest.fn(() => new Promise((resolve, reject) => resolve(credentials))), // eslint-disable-line no-unused-vars
resetGenericPassword: jest.fn(() => new Promise((resolve, reject) => resolve(true))) // eslint-disable-line no-unused-vars
};
});
然后,我为使用该库的功能编写了测试:
import * as keyChainFunctions from "react-native-keychain";
import { setToken, getToken, clearToken } from "./secureStorage";
const token = "abcdefghijklmnopqrstuvwxyz0123456789";
describe("set token", () => {
it("saves the token in the keychain", () => {
expect.assertions(1);
return setToken(token).then(res => {
console.log(res);
console.log(keyChainFunctions);
expect(keyChainFunctions.setGenericPassword).toHaveBeenCalledWith("session", token);
});
});
});
问题是,测试失败。我收到错误消息:
FAIL app/api/secureStorage/secureStorage.test.js
set token
✕ saves the token in the keychain (42ms)
● set token › saves the token in the keychain
expect(jest.fn())[.not].toHaveBeenCalledWith()
jest.fn() value must be a mock function or spy.
Received: undefined
10 | console.log(res);
11 | console.log(keyChainFunctions);
> 12 | expect(keyChainFunctions.setGenericPassword).toHaveBeenCalledWith("session", token);
| ^
13 | });
14 | });
15 | });
at app/api/secureStorage/secureStorage.test.js:12:52
at tryCallOne (node_modules/promise/lib/core.js:37:12)
at node_modules/promise/lib/core.js:123:15
at flush (node_modules/asap/raw.js:50:29)
● set token › saves the token in the keychain
expect.assertions(1)
Expected one assertion to be called but received zero assertion calls.
6 | describe("set token", () => {
7 | it("saves the token in the keychain", () => {
> 8 | expect.assertions(1);
| ^
9 | return setToken(token).then(res => {
10 | console.log(res);
11 | console.log(keyChainFunctions);
at Object.<anonymous> (app/api/secureStorage/secureStorage.test.js:8:12)
和console.log()
的收益:
console.log app/api/secureStorage/secureStorage.test.js:10
true
console.log app/api/secureStorage/secureStorage.test.js:11
{ default:
{ addMatchers: [Function: addMatchers],
advanceTimersByTime: [Function: advanceTimersByTime],
autoMockOff: [Function: disableAutomock],
autoMockOn: [Function: enableAutomock],
clearAllMocks: [Function: clearAllMocks],
clearAllTimers: [Function: clearAllTimers],
deepUnmock: [Function: deepUnmock],
disableAutomock: [Function: disableAutomock],
doMock: [Function: mock],
dontMock: [Function: unmock],
enableAutomock: [Function: enableAutomock],
fn: [Function: bound fn],
genMockFromModule: [Function: genMockFromModule],
isMockFunction: [Function: isMockFunction],
mock: [Function: mock],
requireActual: [Function: bound requireModule],
requireMock: [Function: bound requireMock],
resetAllMocks: [Function: resetAllMocks],
resetModuleRegistry: [Function: resetModules],
resetModules: [Function: resetModules],
restoreAllMocks: [Function: restoreAllMocks],
retryTimes: [Function: retryTimes],
runAllImmediates: [Function: runAllImmediates],
runAllTicks: [Function: runAllTicks],
runAllTimers: [Function: runAllTimers],
runOnlyPendingTimers: [Function: runOnlyPendingTimers],
runTimersToTime: [Function: runTimersToTime],
setMock: [Function: setMock],
setTimeout: [Function: setTimeout],
spyOn: [Function: bound spyOn],
unmock: [Function: unmock],
useFakeTimers: [Function: useFakeTimers],
useRealTimers: [Function: useRealTimers] } }
这告诉我:
1.要么进行模拟工作(因为正确返回了true),要么从React Native Keychain调用了实际的setGenericPassword
函数。
2.由于某种原因,定义了keychainfunctions
,但它是jest.mock
对象而不是三个模拟函数。
如果该模拟有效,则感觉1和2相互矛盾。
我究竟做错了什么?为什么这个模拟不起作用?如何解释这些奇怪的console.log()
和失败的测试?
Bamse仅导出对象。此解决方法有效。我仍然会对如何正确地做/我做错了感兴趣。
const token = "abcdefghijklmnopqrstuvwxyz0123456789";
const credentials = {
username: "session",
password: token
};
export const setGenericPassword = jest.fn(
(username, password) => new Promise((resolve, reject) => resolve(true)) // eslint-disable-line no-unused-vars
);
export const getGenericPassword = jest.fn(
() => new Promise((resolve, reject) => resolve(credentials)) // eslint-disable-line no-unused-vars
);
export const resetGenericPassword = jest.fn(() => new Promise((resolve, reject) => resolve(true))); // eslint-disable-line no-unused-vars