在 Facebook,我們使用 Jest 來測試React Native應用程序。
從 react-native 0.38 版開始,運行?react-native init
?. 以下配置應自動添加到 package.json 文件中:
// package.json
"scripts": {
"test": "jest"
},
"jest": {
"preset": "react-native"
}
注意:如果你正在升級 react-native 應用程序并且之前使用了?jest-react-native
?預設(shè),請從?package.json
?文件中刪除依賴項并將預設(shè)更改為?react-native
?。
用 yarn test 來運行 Jest 測試。
下面來為一個入門的小型組件創(chuàng)建一個快照測試,它的內(nèi)部有些View、Text組件和一些樣式:
// Intro.js
import React, {Component} from 'react';
import {StyleSheet, Text, View} from 'react-native';
const styles = StyleSheet.create({
container: {
alignItems: 'center',
backgroundColor: '#F5FCFF',
flex: 1,
justifyContent: 'center',
},
instructions: {
color: '#333333',
marginBottom: 5,
textAlign: 'center',
},
welcome: {
fontSize: 20,
margin: 10,
textAlign: 'center',
},
});
export default class Intro extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>Welcome to React Native!</Text>
<Text style={styles.instructions}>
這是一個 React Native 快照測試。
</Text>
</View>
);
}
}
現(xiàn)在,使用React的test renderer和Jest的快照特性來和組件交互,獲得渲染結(jié)果和生成快照文件:
// __tests__/Intro-test.js
import React from 'react';
import renderer from 'react-test-renderer';
import Intro from '../Intro';
test('renders correctly', () => {
const tree = renderer.create(<Intro />).toJSON();
expect(tree).toMatchSnapshot();
});
當你運行 ?npm test
? 或者 ?jest
?,將產(chǎn)生一個像下面的文件:
// __tests__/__snapshots__/Intro-test.js.snap
exports[`Intro renders correctly 1`] = `
<View
style={
Object {
"alignItems": "center",
"backgroundColor": "#F5FCFF",
"flex": 1,
"justifyContent": "center",
}
}>
<Text
style={
Object {
"fontSize": 20,
"margin": 10,
"textAlign": "center",
}
}>
Welcome to React Native!
</Text>
<Text
style={
Object {
"color": "#333333",
"marginBottom": 5,
"textAlign": "center",
}
}>
This is a React Native snapshot test.
</Text>
</View>
`;
下次你運行測試時,渲染的結(jié)果將會和之前創(chuàng)建的快照進行比較??煺諔c代碼更改一起提交。當快照測試失敗,你需要去檢查是否是你想要或不想要的變動。 如果變動符合預期,你可以通過?jest -u
?調(diào)用Jest從而重寫存在的快照。
示例代碼可在 examples/enzyme 找到。
預設(shè)設(shè)置了環(huán)境,并且非常的牢固,并且基于我們在 Facebook 發(fā)現(xiàn)的有用內(nèi)容。所有配置選項都可以被覆蓋,就像在不使用預設(shè)時可以自定義一樣。
?react-native
?附帶一個 Jest 預設(shè),因此?jest.preset
?您的字段?package.json
?應該指向?react-native
?. 預設(shè)是一個模仿 React Native 應用程序環(huán)境的節(jié)點環(huán)境。因為它不加載任何 DOM 或瀏覽器 API,所以大大縮短了 Jest 的啟動時間。
該transformIgnorePatterns選項可用于指定 Babel 應轉(zhuǎn)換哪些文件。不幸的是,許多 react-native npm 模塊在發(fā)布之前沒有預編譯它們的源代碼。
默認情況下, jest-react-native 預設(shè)只處理項目自己的源文件和 react-native。如果有必須轉(zhuǎn)換的 npm 依賴項,可以通過包含 react-native 以外的模塊來自定義此配置選項:
"transformIgnorePatterns": [
"node_modules/(?!(react-native|my-project|react-native-button)/)"
]
如果想為每個測試文件提供額外的配置,可以使用?setupFiles
?配置選項來指定安裝腳本。
moduleNameMapper可用于一個模塊路徑映射到不同的模塊。默認情況下,預設(shè)將所有圖像映射到圖像存根模塊,但如果找不到模塊,此配置選項可以提供幫助:
"moduleNameMapper": {
"my-module.js": "<rootDir>/path/to/my-module.js"
}
內(nèi)置的 Jest 預設(shè)?react-native
?附帶了一些應用于 react-native 存儲庫的默認模擬。但是,一些 react-native 組件或第三方組件依賴于本地代碼來呈現(xiàn)。在這種情況下,Jest 的手動模擬系統(tǒng)可以幫助模擬底層實現(xiàn)。
例如,如果你的代碼依賴于一個名為?react-native-video
?的第三方本機視頻組件,你可能希望使用這樣的手動模擬將其存根:
jest.mock('react-native-video', () => 'Video');
這將使組件呈現(xiàn)為?<Video{…props}/>
?,其所有道具都將顯示在快照輸出中。想了解更多還可以閱讀 caveats around Enzyme and React 16.
有時需要提供更復雜的手動模擬。例如,如果想將原生組件的 prop 類型或靜態(tài)字段轉(zhuǎn)發(fā)到模擬,可以通過 jest-react-native 的這個助手從模擬中返回不同的 React 組件:
jest.mock('path/to/MyNativeComponent', () => {
const mockComponent = require('react-native/jest/mockComponent');
return mockComponent('path/to/MyNativeComponent');
});
或者,如果想創(chuàng)建自己的手動模擬,可以執(zhí)行以下操作:
jest.mock('Text', () => {
const RealComponent = jest.requireActual('Text');
const React = require('React');
class Text extends React.Component {
render() {
return React.createElement('Text', this.props, this.props.children);
}
}
Text.propTypes = RealComponent.propTypes;
return Text;
});
在其他情況下,想要模擬不是 React 組件的本機模塊。可以應用相同的技術(shù)。我們建議在真實設(shè)備上運行 React Native 應用程序時檢查原生模塊的源代碼并記錄模塊,然后在真實模塊之后對手動模擬進行建模。
如果你最終一遍又一遍地模擬相同的模塊,建議在單獨的文件中定義這些模擬并將其添加到?setupFiles
?.
更多建議: