我正在尝试成功运行react-native安装附带的boiler place App-test.js测试。我已经看到此测试在其他项目中“开箱即用”,但是,由于我们与 Firebase SDK 的集成,我的测试失败了。长期目标是构建一个测试套件来模拟对我们的 firebase SDK 的调用(想要探索以下解决方案:https://medium.com/stories-from-upstatement/jest-mocks-roasting-on -an-open-firestore-36fa55b76953,如何使用 Jest 模拟 Firebase Firestore 方法?),但我被困在了大门前。
这是我在尝试运行以下命令时收到的初始错误:
npm test __tests__/App-test.js
错误:
import { getFirebaseRoot } from './internal/registry/namespace';
export default () => ({
^^^^^^
SyntaxError: Cannot use import statement outside a module
1 | import React from 'react';
> 2 | import firebase from '@react-native-firebase/app';
| ^
3 | import analytics from '@react-native-firebase/analytics';
4 | import '@react-native-firebase/auth';
5 | import '@react-native-firebase/database';
看来我们的 App.js 文件是罪魁祸首。
import React from 'react';
import firebase from '@react-native-firebase/app';
import analytics from '@react-native-firebase/analytics';
import '@react-native-firebase/auth';
import '@react-native-firebase/database';
import '@react-native-firebase/crashlytics';
import '@react-native-firebase/functions';
import '@react-native-firebase/storage';
import { Provider } from 'react-redux';
import store from './app/store';
import Navigator from './app/routes';
import { loginUser } from './app/domain/Common/auth/actions';
export default class App extends React.Component {
constructor(props) {
super(props);
this.props = props;
}
// gets the current screen from navigation state
getActiveRouteName = (navigationState) => {
let routeName = null;
if (!navigationState) {
return null;
}
const route = navigationState.routes[navigationState.index];
// dive into nested navigators
if (route.routes) {
return getActiveRouteName(route);
}
routeName = route.routeName;
// for venues, append specific venue name
if (route.params && route.params.venueName) {
routeName += ` - ${route.params.venueName}`;
}
return routeName;
}
render() {
return (
<Provider store={store}>
<Navigator
onNavigationStateChange={(prevState, currentState) => {
// track user screen changes in Analytics
const currentScreen = this.getActiveRouteName(currentState);
const prevScreen = this.getActiveRouteName(prevState);
if (prevScreen !== currentScreen) {
analytics().setCurrentScreen(currentScreen);
}
}} />
</Provider>
);
}
}
研究此问题后,解决该问题最有希望的方法如下,https://github.com/invertase/react-native-firebase/issues/3035.
但是我现在遇到了一个新错误:
FAIL __tests__/App-test.js
● Test suite failed to run
/Users/kyjelly/micturnTwo/node_modules/react-native/Libraries/Utilities/warnOnce.js:15
const warnedKeys: {[string]: boolean} = {};
^^^^^^^^^^
SyntaxError: Missing initializer in const declaration
at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:537:17)
at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:579:25)
at Object.<anonymous> (node_modules/react-native/Libraries/react-native/react-native-implementation.js:14:18)
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 3.101s
这是我的 pacakge.json 的笑话部分
"jest": {
"preset": "react-native",
"transformIgnorePatterns": [
"node_modules/(?!(jest-)?react-native|react-clone-referenced-element|@react-native-community|expo(nent)?|@expo(nent)?/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|@react-native-firebase/app)"
]
}
这是我的 jest.config.js
module.exports = {
verbose: true,
moduleNameMapper: {
'@react-native-firebase/crashlytics': '<rootDir>/__tests__/__mocks__/firebase/crashlytics.js',
}
};
有人能指出我正确的方向吗?据我了解,Jest 在编译某些非本机 Javascript 的文件时遇到问题。但我尝试的每一个解决方案都会导致另一个配置尝试的兔子洞。
我有一个对我有用的修复程序,它与忽略库无关,而是配置 Jest 来模拟我将要使用的函数。我已关注您粘贴的链接上的此评论。
最后我的代码如下所示:
export const setupModulesMock = (() => {
jest.mock('@react-native-firebase/crashlytics', () => {
return () => ({
log: jest.fn(),
recordError: jest.fn(),
// Any function you want to use or mock
});
});
})();
理想情况下,软件包应提供笑话设置。但是,由于它不可用,您需要为 Firebase 包的每个模块创建模拟实现。
我放置了两个文件 -
jest.config.js
和 jest.setup.js
,后者在前者中被引用为配置的 setupFiles
属性的值。
除了其他模拟实现之外,对于 Firebase,这些是我的设置。您可以根据您的用例修改它们。
const mockedFirebaseCrashlyticsLog = jest.fn()
const mockedFirebaseCrashlyticsRecordError = jest.fn()
jest.mock('@react-native-firebase/crashlytics', () => {
return () => ({
log: mockedFirebaseCrashlyticsLog,
recordError: mockedFirebaseCrashlyticsRecordError
})
})
const mockedFirebaseAuthSignInWithCustomToken = jest.fn()
jest.mock('@react-native-firebase/auth', () => () => {
return {
signInWithCustomToken: mockedFirebaseAuthSignInWithCustomToken
}
})
const mockedFirestoreCollection = jest.fn()
jest.mock('@react-native-firebase/firestore', () => () => {
return {
collection: mockedFirestoreCollection
}
})
const mockedFirebaseAnalyticsLogEvent = jest.fn()
const mockedFirebaseAnalyticsLogLogin = jest.fn()
const mockedFirebaseAnalyticsSetUserId = jest.fn()
jest.mock('@react-native-firebase/analytics', () => () => {
return {
logEvent: mockedFirebaseAnalyticsLogEvent,
logLogin: mockedFirebaseAnalyticsLogLogin,
setUserId: mockedFirebaseAnalyticsSetUserId
}
})
我通过以这种方式创建
@react-native-firebase/dynamic-links
的模拟解决了这个问题
jest.mock('@react-native-firebase/dynamic-links', () => {
return () => ({
onLink: jest.fn(),
});
});
如果您有
jest.setup.js
文件或 ___mocks___
文件夹,您可能需要将此代码添加到其中之一:
jest.mock("@react-native-firebase/analytics", () => ({
analytics: jest.fn(() => ({
logEvent: jest.fn(),
setUserProperties: jest.fn(),
setUserId: jest.fn(),
setCurrentScreen: jest.fn(),
})),
}));
就我而言,我只安装了:
"@react-native-firebase/app": "^20.3.0",
"@react-native-firebase/auth": "^20.0.0",
"@react-native-firebase/messaging": "^20.3.0",
所以,我的mock文件如下所示:
// rn-firebase.js
import {jest} from '@jest/globals';
jest.mock('@react-native-firebase/app', () => {
return () => ({
delete: jest.fn(),
});
});
jest.mock('@react-native-firebase/auth', () => {
return () => ({
onAuthStateChanged: jest.fn(),
});
});
jest.mock('@react-native-firebase/messaging', () => {
const module = () => ({
getToken: jest.fn(() => '1234'),
});
module.AuthorizationStatus = {
NOT_DETERMINED: -1,
DENIED: 0,
AUTHORIZED: 1,
PROVISIONAL: 2,
};
return module;
});
我把它放在
setupFilesAfterEnv
文件上的jest.config.js
列表中:
// jest.config.js
module.exports = {
preset: 'react-native',
~ ~ ~
setupFilesAfterEnv: [
'<rootDir>/mocks/rn-firebase.js',
],
~ ~ ~
这些工作正常。