[英]Testing React Native apps with Jest
我一直試圖讓Jest使用我的反應原生項目而沒有太多運氣。 似乎大多數線程都是被黑客攻擊的解決方案,以便讓事情正常運行,我似乎無法克服我面臨的最后一個障礙。
嘗試運行以下代碼時,我收到以下錯誤。 如果我在jestSupport / env.js文件中模擬react-native我可以通過錯誤,但顯然我不能使用任何結構(如AsyncStorage)來實際測試我的代碼(因為我只有模擬功能)。
有沒有人對如何解決這個問題有任何建議?
在這個階段,我願意嘗試任何事情,包括廢棄我所擁有的所有測試,然后再試一次。 如果是這種情況,我需要遵循一些指導原則,因為React Native文檔在Jest方面可能已經過時,而且我對React場景相對較新。
Runtime Error
Error: Cannot find module 'ReactNative' from 'react-native.js'
at Runtime._resolveNodeModule (/Users/Yulfy/Downloads/COMPANY-Mobile/node_modules/jest-cli/src/Runtime/Runtime.js:451:11)
at Object.<anonymous> (/Users/Yulfy/Downloads/COMPANY-Mobile/node_modules/react-native/Libraries/react-native/react-native.js:181:25)
at Object.<anonymous> (/Users/Yulfy/Downloads/COMPANY-Mobile/network/connections.js:8:18)
jest.unmock('../network/connections');
import Authorisation from '../network/connections';
describe('connections', () => {
it('Should store and retrieve a mocked user object', () => {
Auth = new Authorisation();
const TEST_STRING = "CONNECTION TEST PASS";
var userObj = {
test_string: TEST_STRING
};
Auth._localStore(userObj, (storeRes) => {
Auth._localRetrieve((retRes) => {
expect(retRes.test_string).toEqual(TEST_STRING);
});
});
});
});
/*
* All returns should give the following structure:
* {isSuccess: boolean, data: object}
*/
import React, { Component } from 'react';
import { AsyncStorage } from 'react-native';
const Firebase = require('firebase');
const FIREBASE_URL = 'https://COMPANY-test.firebaseio.com';
const STORAGE_KEY = 'USER_DATA';
class Authorisation{
_ref = null;
user = null;
constructor(){
}
getOne(){return 1;}
_setSystemUser(userObj, authObj, callback){
var ref = this.connect();
if(ref === null){
callback({isSuccess:false, data:{message:"Could not connect to the server"}});
}
ref = ref.child('users').child(authObj.uid);
ref.once("value", function(snapshot){
if(snapshot.exists()){
callback({isSuccess:false, data:{message:"Email is currently in use"}});
return;
}
ref.set(userObj, function(error){
if(error){
callback({isSuccess:false, data:error});
}else{
callback({isSuccess:true, data:authObj});
}
});
});
}
_localStore(userObj, callback){
AsyncStorage.setItem(STORAGE_KEY, userObj, (error) => {
console.log("_localStore::setItem -> ", error);
if(error){
callback({
isSuccess:false,
data:'Failed to store user object in storage.'
});
}else{
callback({
isSuccess:true,
data: userObj
});
}
});
}
_localRetrieve(callback){
AsyncStorage.getItem(STORAGE_KEY, (error, res) => {
console.log("_localStore::getItem:error -> ", error);
console.log("_localStore::getItem:result -> ", res);
if(error){
callback({
isSuccess:false,
data:error
});
}else{
callback({
isSuccess: true,
data: res
});
}
});
}
connect(){
if(this._ref === null){
_ref = new Firebase(FIREBASE_URL);
}
return _ref;
}
getUser(){
}
isLoggedIn(){
}
registerUser(userObj, callback){
var ref = this.connect();
if(ref === null){
callback({isSuccess:false, data:{message:"Could not connect to the server"}});
}
var that = this;
ref.createUser({
email: userObj.username,
password: userObj.password
}, function(error, userData){
if(error){
callback({isSuccess:false, data:error});
return;
}
var parseObj = {
email: userObj.username,
fullName: userObj.fullName
};
that.loginUser(parseObj, function(res){
if(res.isSuccess){
that._setSystemUser(parseObj, res.data, callback);
}else{
callback(res);//Fail
}
});
});
}
loginUser(userObj, callback){
var ref = this.connect();
if(ref === null){
callback({isSuccess:false, data:{message:"Could not connect to the server"}});
}
ref.authWithPassword({
email: userObj.email,
password: userObj.password
}, function(error, authData){
if(error){
callback({isSuccess:false, data:error.message});
}else{
callback({isSuccess:true, data:authData});
}
});
}
}
export default Authorisation;
如果您已經讀過這篇文章,感謝您的時間!
-Yulfy
TL; DR
我有一個Jest運行的例子,在這個GitHub Repo中運行最新版本的React Native( v0.28.0
)。
-
經過一段時間調查這個問題后,我終於找到了解決方案。
有一些與Jest集成的React Native應用程序的在線示例,但不幸的是,您不能簡單地將代碼復制並粘貼到代碼庫中並期望它能夠正常工作。 這是因為RN版本的差異。
在v0.20.0
之前的React Native版本在v0.20.0
包含一個.babelrc
文件( node_modules/react-native/packager/react-packager/.babelrc
),一些在線示例直接將它包含在package.json
。 但是, v0.20.0
及更高版本v0.20.0
更改為不再包含此文件,這意味着您無法再嘗試包含該文件。 因此,我建議使用您自己的.babelrc
文件並對您自己的預設和插件進行definte。
我不知道你的package.json
文件是什么樣的,但是解決這個問題是一個非常重要的部分。
{
"name": "ReactNativeJest",
"version": "0.0.1",
"jest": {
"scriptPreprocessor": "<rootDir>/node_modules/babel-jest",
"unmockedModulePathPatterns": [
"node_modules"
],
"verbose": true,
"collectCoverage": true
},
"scripts": {
"test": "jest"
},
"dependencies": {
"react": "^15.1.0",
"react-native": "^0.27.2"
},
"devDependencies": {
"babel-core": "^6.4.5",
"babel-jest": "^12.1.0",
"babel-plugin-transform-regenerator": "^6.0.18",
"babel-polyfill": "^6.0.16",
"babel-preset-react-native": "^1.9.0",
"babel-types": "^6.1.2",
"chai": "^3.5.0",
"enzyme": "^2.3.0",
"jest-cli": "^12.1.1",
"react-addons-test-utils": "^15.1.0",
"react-dom": "^15.1.0"
}
}
另一個重要的部分是模仿React Native。 我創建了一個__mocks__/react-native.js
文件,如下所示:
'use strict';
var React = require('react');
var ReactNative = React;
ReactNative.StyleSheet = {
create: function(styles) {
return styles;
}
};
class View extends React.Component {}
class Text extends React.Component {}
class TouchableHighlight extends React.Component {}
// Continue to patch other components as you need them
ReactNative.View = View;
ReactNative.Text = Text;
ReactNative.TouchableHighlight = TouchableHighlight;
module.exports = ReactNative;
通過猴子修補這樣的React Native函數,您可以成功避免在嘗試運行測試時遇到的奇怪的Jest錯誤。
最后,確保在項目的根目錄中創建一個.babelrc
文件,該文件至少包含以下幾行:
{
"presets": ["react-native"],
"plugins": [
"transform-regenerator"
]
}
該文件將用於告訴babel如何正確轉換您的ES6代碼。
完成此設置后,使用React Native運行Jest應該沒有問題。 我相信React Native的未來版本將更容易將兩個框架集成在一起,但這種技術將完美適用於當前版本:)
您可以使用react-native-mock庫為您進行模擬 (確保將庫添加到package.json
文件中),而不是手動模擬__mocks__/react-native.js
文件中的ReactNative元素:
// __mocks__/react-native.js
module.exports = require('react-native-mock');
我更新了我的GitHub Repo示例以演示此方法。
您是否嘗試在測試文件中模擬react-native?
它適用於我的測試用例:
jest.dontMock(`../my-module-that-uses React-native.AsyncStorage`);
jest.setMock(`react-native`, {
AsyncStorage: {
multiGet: jest.fn(),
},
});
const ReactNative = require(`react-native`);
const {AsyncStorage, } = ReactNative;
const myModule = require(`../my-module-that-uses React-native.AsyncStorage`);
// Do some tests and assert ReactNative.AsyncStorage.multiGet calls
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.