React 單元測試

1于置、Mocha測試掃盲

a、測試腳本里面應(yīng)該包括一個或多個describe塊,每個describe塊應(yīng)該包括一個或多個it塊嚼松。

// add.js
function add(x, y) {
  return x + y;
}
module.exports = add;

// add.test.js
var add = require('./add.js');
var expect = require('chai').expect;       // 引入斷言庫 chai , Mocha本身不提供(Mocha并不限制使用哪一種斷言庫)

describe('加法函數(shù)的測試', function() {
  it('1 加 1 應(yīng)該等于 2', function() {
    expect(add(1, 1)).to.be.equal(2);
  });
});

b、describe塊稱為"測試套件"(test suite)锰扶,表示一組相關(guān)的測試献酗。它是一個函數(shù),第一個參數(shù)是測試套件的名稱("加法函數(shù)的測試")坷牛,第二個參數(shù)是一個實際執(zhí)行的函數(shù)罕偎。
c、it塊稱為"測試用例"(test case)京闰,表示一個單獨的測試颜及,是測試的最小單位甩苛。它也是一個函數(shù),第一個參數(shù)是測試用例的名稱("1 加 1 應(yīng)該等于 2")俏站,第二個參數(shù)是一個實際執(zhí)行的函數(shù)讯蒲。
d、expect斷言的寫法都是一樣的肄扎。頭部是expect方法爱葵,尾部是斷言方法,比如equal反浓、a/an萌丈、ok、match等雷则。兩者之間使用to或to.be連接辆雾。

// 相等或不相等
expect(4 + 5).to.be.equal(9);
expect(4 + 5).to.be.not.equal(10);
expect(foo).to.be.deep.equal({ bar: 'baz' });

// 布爾值為true
expect('everthing').to.be.ok;
expect(false).to.not.be.ok;

// typeof
expect('test').to.be.a('string');
expect({ foo: 'bar' }).to.be.an('object');
expect(foo).to.be.an.instanceof(Foo);

// include
expect([1,2,3]).to.include(2);
expect('foobar').to.contain('foo');
expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');

// empty
expect([]).to.be.empty;
expect('').to.be.empty;
expect({}).to.be.empty;

// match
expect('foobar').to.match(/^foo/);

e、mocha --recursive 命令會執(zhí)行test目錄下的所有test測試腳本
f月劈、異步測試:Mocha默認(rèn)每個測試用例最多執(zhí)行2000毫秒度迂,如果到時沒有得到結(jié)果,就報錯猜揪。對于涉及異步操作的測試用例惭墓,這個時間往往是不夠的,需要用-t或--timeout參數(shù)指定超時門檻(mocha -t 5000 timeout.test.js)
g而姐、Mocha內(nèi)置對Promise的支持腊凶,允許直接返回Promise,等到它的狀態(tài)改變拴念,再執(zhí)行斷言钧萍,而不用顯式調(diào)用done方法

it('異步請求應(yīng)該返回一個對象', function() {
  return fetch('https://api.github.com')
    .then(function(res) {
      return res.json();
    }).then(function(json) {
      expect(json).to.be.an('object');
    });
});

h、大型項目有很多測試用例政鼠。有時风瘦,我們希望只運行其中的幾個,這時可以用only方法公般。describe塊和it塊都允許調(diào)用only方法万搔,表示只運行某個測試套件或測試用例。

it.only('1 加 1 應(yīng)該等于 2', function() {
  expect(add(1, 1)).to.be.equal(2);
});

2官帘、React 單元測試

a瞬雹、一個React組件有兩種存在形式:虛擬DOM對象(即React.Component的實例)和真實DOM節(jié)點。官方測試工具庫對這兩種形式遏佣,都提供測試解決方案挖炬。

Shallow Rendering:測試虛擬DOM的方法(將一個組件渲染成虛擬DOM對象,但是只渲染第一層,不渲染所有子組件)
DOM Rendering: 測試真實DOM的方法

b意敛、Enzyme庫:官方測試工具庫的封裝馅巷,它模擬了jQuery的API,非常直觀

// 1草姻、shallow
import {shallow} from 'enzyme';

describe('Enzyme Shallow', function () {
  it('App\'s title should be Todos', function () {
    let app = shallow(<App/>);
    expect(app.find('h1').text()).to.equal('Todos');
  });
};

// 2钓猬、render(將React組件渲染成靜態(tài)的HTML字符串,然后分析這段HTML代碼的結(jié)構(gòu)撩独,返回一個對象)
// 適用于依賴類名做測試
import {render} from 'enzyme';

describe('Enzyme Render', function () {
  it('Todo item should not have todo-done class', function () {
    let app = render(<App/>);
    expect(app.find('.todo-done').length).to.equal(0);
  });
});

// 3敞曹、mount(將React組件加載為真實DOM節(jié)點,要求存在一個真實的DOM環(huán)境综膀,否則會報錯澳迫。因此,測試用例之中剧劝,DOM環(huán)境(即window, document 和 navigator 對象)必須是存在的橄登,[jsdom](https://github.com/tmpvar/jsdom) 庫提供這項功能。)
// 修改package.json的test字段如下:
{
  "scripts": {
    "test": "mocha --compilers js:babel-core/register --require ./test/setup.js",
  },
}

// setup.js
import jsdom from 'jsdom';
if (typeof document === 'undefined') {
  global.document = jsdom.jsdom('<!doctype html><html><body></body></html>');
  global.window = document.defaultView;
  global.navigator = global.window.navigator;
}

//  test.js
import {mount} from 'enzyme';

describe('Enzyme Mount', function () {
  it('Delete Todo', function () {
    let app = mount(<App/>);
    let todoLength = app.find('li').length;
    app.find('button.delete').at(0).simulate('click');
    expect(app.find('li').length).to.equal(todoLength - 1);
  });
});

c讥此、Enzyme的常用API

.get(index):返回指定位置的子組件的DOM節(jié)點
.at(index):返回指定位置的子組件
.first():返回第一個子組件
.last():返回最后一個子組件
.type():返回當(dāng)前組件的類型
.text():返回當(dāng)前組件的文本內(nèi)容
.html():返回當(dāng)前組件的HTML代碼形式
.props():返回根組件的所有屬性
.prop(key):返回根組件的指定屬性
.state([key]):返回根組件的狀態(tài)
.setState(nextState):設(shè)置根組件的狀態(tài)
.setProps(nextProps):設(shè)置根組件的屬性
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拢锹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子萄喳,更是在濱河造成了極大的恐慌卒稳,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件他巨,死亡現(xiàn)場離奇詭異充坑,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)闻蛀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門匪傍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來您市,“玉大人觉痛,你說我怎么就攤上這事∫鹦荩” “怎么了薪棒?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長榕莺。 經(jīng)常有香客問我俐芯,道長,這世上最難降的妖魔是什么钉鸯? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任吧史,我火速辦了婚禮,結(jié)果婚禮上唠雕,老公的妹妹穿的比我還像新娘贸营。我一直安慰自己吨述,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布钞脂。 她就那樣靜靜地躺著揣云,像睡著了一般。 火紅的嫁衣襯著肌膚如雪冰啃。 梳的紋絲不亂的頭發(fā)上邓夕,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機(jī)與錄音阎毅,去河邊找鬼焚刚。 笑死,一個胖子當(dāng)著我的面吹牛扇调,可吹牛的內(nèi)容都是我干的汪榔。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼肃拜,長吁一口氣:“原來是場噩夢啊……” “哼痴腌!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起燃领,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤士聪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后猛蔽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體剥悟,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年曼库,在試婚紗的時候發(fā)現(xiàn)自己被綠了区岗。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡毁枯,死狀恐怖慈缔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情种玛,我是刑警寧澤藐鹤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站赂韵,受9級特大地震影響娱节,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜祭示,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一肄满、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦稠歉、人聲如沸讥电。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽恩敌。三九已至,卻和暖如春横媚,著一層夾襖步出監(jiān)牢的瞬間纠炮,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工灯蝴, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留恢口,地道東北人。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓穷躁,卻偏偏與公主長得像耕肩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子问潭,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,927評論 2 355