react-native使用jest、enzyme進行單元測試

来源:https://www.cnblogs.com/muyunren/archive/2018/01/19/8318532.html
-Advertisement-
Play Games

在網上找了好久針對react-native的測試方法,但是沒有找到靠譜的方式。要麼很淺只是跑了一下官方的例子,要麼就是版本有點老舊,照著無法進行。jest提供的react-native例子很少,而enzyme提供的react-native-mock庫也是各種報錯,讓人很是絕望。於是乎在搜索到的信息指 ...


在網上找了好久針對react-native的測試方法,但是沒有找到靠譜的方式。要麼很淺只是跑了一下官方的例子,要麼就是版本有點老舊,照著無法進行。jest提供的react-native例子很少,而enzyme提供的react-native-mock庫也是各種報錯,讓人很是絕望。於是乎在搜索到的信息指引下,經過自己的嘗試,我總結出了下麵的測試方法,但是不是很滿意,如果哪位大神有更好的方式,懇請留個言指明一下方向。

react官方內置了jest作為單元測試的工具,再搭配上enzyme就能完美地開展測試工作。但是當測試的對象變成react-native時,測試工作就變得異常艱難。艱難的地方主要有以下幾點:

1、原生組件干擾。 2、使用enzyme去渲染react-native組件時,async/await解析存在問題,我預計是報錯了,並且錯誤被吞吃掉了,這就導致react-native組件的渲染結果不值得信任,因為當你在生命周期函數上使用了async等時,基本可以確認它的執行存在問題。 3、組件的文件調用了其他的方法文件時,並且這些方法是非同步操作,包含了數據請求操作等,如何去mock數據並且替換調用。 4、Image組件使用require獲取文件報錯。 基於以上幾點問題,我們開始一一解決。 1、官方提供了配置可以模擬原生組件,當有第三方組件時,可以通過jest.mock方法做模擬。 假定引入了一個第三方組件叫做react-native-go,並且上面有一個方法叫to,然後你在代碼中調用了這個方法,那麼你就可以這樣寫一個假的對象來返回對應方法,具體實現如下
jest.mock('react-native-go', ()=>{
    return {
        to: ()=>{}
    }
});
2、竟然內部調用async有問題,那麼我們可不可以直接在外部調用內部方法呢?當然你直接用shallow返回的組件對象去調用內部方法是不行的,這時候只會報錯,說你調用的對象不是函數。那麼怎麼得到this指針呢?組件在初始化時會執行各個生命周期函數,而我們可以通過props傳遞函數給組件來調用,這就有解決無法獲取this的問題的途徑了。接著我們就可以通過閉包函數和修改函數指針的方式來把this暴露到測試環境中。 3、組件內部引用了外部文件。這個也簡單了,基於第二點的辦法,我們就可以造一個測試專用的方法對象來替換掉實際使用的工具對象,通過props和生命周期函數直接覆蓋掉,這樣再加上mockjs便可以模擬數據。 4、參照官方文檔中Image的另一個調用方式是uri,並且可以直接傳入base64文件,那麼我們就可以把require去掉,改成直接引用base64文件。而圖片轉換base64,我們可以通過nodejs來實現。 通過上面這些方式,我們就可以開始react-native的測試工作了。 具體代碼如下: 首先,按照配置jest測試環境。 1、安裝依賴包
"devDependencies": {
	"enzyme": "^3.3.0",
	"enzyme-adapter-react-16": "^1.1.1",
	"jest": "^21.2.1",
	"react-dom": "^16.2.0"
},

2、編寫.babelrc

{
  "presets": ["react-native"]
}

3、jest配置

// package.json
  "scripts": {
    "test": "jest"
  },
  "jest": {
    "preset": "react-native"
  }

先寫一個我要測試的組件

import React, {Component} from 'react';
import {
  View
} from 'react-native';

//工具方法包含獲取數據請求send
let Core = require('./core');

export default class AboutUsPage extends Component<{}>{
  constructor(props){
    super(props);
    if(typeof this.props.getThis === 'function'){
      this.props.getThis.call(this);
      if (this.props.testCore) {
        Core = this.props.testCore;
      }
    }
  }
  async componentWillMount(){
    this.setState({
      name: await this.firstStep()
    })
  }
  async firstStep(){
    return await this.secondStep();
  }
  async secondStep(){
    return await Core.send('/getData');
  }
  render(){
    return (
      <View></View>
    )
  }
}

core文件

let Core = {
    async send() {//請求非同步數據,返回promise
        ...
    }
};
module.exports = Core;

testCore文件,暴露兩個函數,一個send用以調用數據,一個setSendData用以設置要返回的數據

"use strict";

let caches = {
};

let currentRequest = {};
let Core = {
  async setSendData(key, status, data) {
    caches[key] = {
      status,
      data
    };
  },
  async send(key){
    let res = caches[key];
    if(res.status){
      return Promise.resolve(res.data);
    }else{
      return Promise.reject(res.data);
    }
  }
};

module.exports = Core;

test.js測試文件

'use strict';
import React from 'react';
import AboutUsPage from './AboutUsPage';
import {configure, shallow} from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import testCore from './test.core';

configure({ adapter: new Adapter() });

testCore.setSendData('getData', true, 'aaa');

describe('AboutUsPage', () => {
  let component;
  let wrapper;
  wrapper = shallow(<AboutUsPage getThis={function(){component=this;}} testCore={testCore}/>);
  wrapper.setState({
    name: 'tom'
  });
  it('renders correctly', async () => {
    await component.componentWillMount();
    expect(wrapper.state().name).toBe('aaa');
  });
  
});

  

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 學習目標 資料庫管理員(DBA)任務和工具 Oracle軟體安裝 Oracle Grid Infrastructure安裝 Oracle DB安裝 Oracle DB管理員的任務 設計、實施和維護Oracle資料庫任務: 1.評估資料庫伺服器硬體 2.制定Oracle軟體安裝計劃 3.制定資料庫和安 ...
  • 一:需求簡介 之前boss提出一個需求,運行在廣告機上的app,需要完成自動升級的功能,廣告機是非觸摸屏的,不能通過手動點擊,所以app必須做到自動下載,自動安裝升級,並且安裝完成後,app還要繼續運行,最好不藉助其它app來實現以上功能。 二:實現思路 實現這個功能第一個想到的方法就是靜默安裝,由 ...
  • 原文鏈接:一句代碼載入網路圖片到ImageView——Android Picasso 在這裡介紹一個Android框架:Picasso。 picasso是Square公司開源的一個Android圖形緩存庫,地址http://square.github.io/picasso/,可以實現圖片下載和緩存功 ...
  • 這是一個點擊之後反應超時的ANR 初步判斷是系統和服務占用資源太多,引起原生設置的ANR在原生設置“語言和輸入法”界面點擊返回鍵是在10:24:52.563,原生設置是在10:24:52.723結束,公司設置是在10:24:57.238才收到onConfigurationChanged回調,快5秒了 ...
  • 。。。求期末不掛。。。 今天完成了第四題,邏輯稍微有點糾纏,但還好問題不是很多 邏輯其實挺複雜的,也可能我基礎太差,還有就是沒來得及寫註釋,很傷。。。 這裡糾結了蠻久的,一直搞不懂這個remove的用法是什麼,好像我裡面沒寫DOM節點的數值也可以刪除。。。 其實想那個刪除對應數值的節點的時候也卡了很 ...
  • 1, 轉義字元 轉義字元:用於表示網頁中的特殊字元 XHTML不直接輸入符號,建議使用轉義字元。 &nbsp 空格; &copy 版權; &reg 註冊商標 如果輸入連續的空格要使用&的轉義字元&(&amp;)nbsp,即&amp;nbsp; 2, 水平線 <Hr> 水平線 <hr width="5 ...
  • xss攻擊(跨站腳本) 是網站應用程式的安全泄露攻擊,是代碼註入的一種。它允許惡意用戶將代碼註入到網頁上,其他用戶在觀看網頁時就會受到影響。 攻擊原理 其特點是不對伺服器端造成任何傷害,而是通過一些正常的站內交互途徑,例如發佈評論,提交含有 JavaScript 的內容文本。這時伺服器端如果沒有過濾 ...
  • 前端框架層出不窮,不過萬變不離其宗,就是從MVC過渡到MVVM。從數據映射到DOM,angular中用的是watcher對象,vue是觀察者模式,react就是state了。 React通過管理狀態實現對組件的管理,通過this.state()方法更新state。當this.setState()被調 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 在我們開發過程中基本上不可或缺的用到一些敏感機密數據,比如SQL伺服器的連接串或者是OAuth2的Secret等,這些敏感數據在代碼中是不太安全的,我們不應該在源代碼中存儲密碼和其他的敏感數據,一種推薦的方式是通過Asp.Net Core的機密管理器。 機密管理器 在 ASP.NET Core ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 順序棧的介面程式 目錄順序棧的介面程式頭文件創建順序棧入棧出棧利用棧將10進位轉16進位數驗證 頭文件 #include <stdio.h> #include <stdbool.h> #include <stdlib.h> 創建順序棧 // 指的是順序棧中的元素的數據類型,用戶可以根據需要進行修改 ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • C總結與剖析:關鍵字篇 -- <<C語言深度解剖>> 目錄C總結與剖析:關鍵字篇 -- <<C語言深度解剖>>程式的本質:二進位文件變數1.變數:記憶體上的某個位置開闢的空間2.變數的初始化3.為什麼要有變數4.局部變數與全局變數5.變數的大小由類型決定6.任何一個變數,記憶體賦值都是從低地址開始往高地 ...
  • 如果讓你來做一個有狀態流式應用的故障恢復,你會如何來做呢? 單機和多機會遇到什麼不同的問題? Flink Checkpoint 是做什麼用的?原理是什麼? ...
  • C++ 多級繼承 多級繼承是一種面向對象編程(OOP)特性,允許一個類從多個基類繼承屬性和方法。它使代碼更易於組織和維護,並促進代碼重用。 多級繼承的語法 在 C++ 中,使用 : 符號來指定繼承關係。多級繼承的語法如下: class DerivedClass : public BaseClass1 ...
  • 前言 什麼是SpringCloud? Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的開發便利性簡化了分散式系統的開發,比如服務註冊、服務發現、網關、路由、鏈路追蹤等。Spring Cloud 並不是重覆造輪子,而是將市面上開發得比較好的模塊集成進去,進行封裝,從 ...
  • class_template 類模板和函數模板的定義和使用類似,我們已經進行了介紹。有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同。類模板用於實現類所需數據的類型參數化 template<class NameType, class AgeType> class Person { publi ...
  • 目錄system v IPC簡介共用記憶體需要用到的函數介面shmget函數--獲取對象IDshmat函數--獲得映射空間shmctl函數--釋放資源共用記憶體實現思路註意 system v IPC簡介 消息隊列、共用記憶體和信號量統稱為system v IPC(進程間通信機制),V是羅馬數字5,是UNI ...