xia的小窩

一起來coding和碼字吧

0%

javascipt-jest基本操作

對於javascript,我們可以使用jest來進行測試。

安裝

我們先安裝node,這個在前面的blog應該有提及,這裡就不放連結了。
直接從npm下手吧。

1
npm install --save-dev jest

我們在資料夾裡建立sum.jssum.test.js,來做簡單的測試。
先撰寫sum.js

1
2
3
4
5
function sum(a, b){
return a + b;
}

module.exports = sum;

接著在sum.test.js裡撰寫

1
2
3
4
5
const sum = require('./sum');

test("adds 1 + 2 to 3 ?", () => {
expect(sum(1, 2)).toBe(3);
});

接著在cmd裡輸入

1
npm test

就可以看見

1
2
3
4
5
6
7
8
PASS  ./sum.test.js
√ adds 1 + 2 to 3 ? (3 ms)

Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.526 s, estimated 1 s
Ran all test suites.

如果有問題,請去package.json裡翻找並修正。

1
2
3
"scripts": {
"test": "jest"
},

匹配器

這裡的toBe叫做匹配器,當然不是只有這個,還有toBeNulltoBeUndefinedtoBeTruthytoBeFalsy……等等。

拋錯

sum.js裡繼續撰寫

1
2
3
4
5
6
7
function  myFunction(input){
if (typeof input !== 'number'){
throw new Error('Invaild Input')
}
}

module.exports = myFunction;

這時候我們可以知道,如果這個input如果不是數字的話,就會拋出錯誤。
那我們就可以在sum.test.js裡寫下

1
2
3
4
5
6
7
const myFunction = require('./sum');

test('throws on invaild input', () => {
expect(() => {
myFunction('ase');
}).toThrow();
})

這個時候會pass,因為它裡面本來就不是數字。

1
2
PASS  ./sum.test.js
√ throws on invaild input (8 ms)

相等

sum.test.js裡撰寫。

1
2
3
4
5
6
7
test('object assignment ', () => {
const data = {
one : 1
};
data['two'] = 2;
expect(data).toEqual({one: 1, two: 2});
})

這裡我們可以一目瞭然的看見toEqual

1
2
PASS  ./sum.test.js
√ object assignment (4 ms)

falsy, thruthy

這裡是針對if的。

1
2
3
4
test('null is falsy ', () => {
const n = null;
expect(n).toBeFalsy();
})

如果null為否,則通過。

1
2
PASS  ./sum.test.js
√ null is falsy (2 ms)

async, await

這裡的話就和機器人那會差不多,jest只要知道它測試的東西是不是完成,就可以往其他地方執行其他程式。

1
2
3
4
5
6
7
8
9
10
11
12
test('the date  is peanute butter', done => {
function callback(data) {
try {
expect(data).toBe('peanute butter');
done();
}catch(error){
done(error);
}
}

fetchData(callback);
})

上面的是測試階段,也就是說我只要知道它執行ok就沒問題咧。

1
2
3
4
5
6
7
function fetchData(callback){
setTimeout(() => {
callback('peanut butter');
}, 1000);
}

module.exports = fetchData;

我這裡定義的是,在1000毫秒之後,回掉這個函式,並傳遞peanut butter這個參數。
setTimeout是模擬等待數據返回的過程。

Promise

我這裡先定義一個fetchPromise

1
2
3
4
5
6
7
function fetchPromise(){
return new Promise((resolve, reject) => {
setTimeout(() => resolve('peanut butter'), 1000);
})
}

module.exports = fetchPromise;

這裡會丟回來一個Promise,在延遲1000毫秒之後,會回傳resolve,並傳遞一個peanut butter
所以,那我們只需要這麼寫

1
2
3
4
test('the data is peanut butter', async () => {
const data = await fetchPromise();
expect(data).toBe('peanut butter');
})

這樣就可以知道這個值是不是一樣了,一樣就會pass

模擬函數

這裡簡單介紹一下mock function

1
2
3
4
5
test('mock implementation of a basic function', () => {
const mock = jest.fn(x => 42 + x);
expect(mock(1)).toBe(43);
expect(mock).toHaveBeenCalledWith(1);
})

第一點,我們先建立一個mock函式,它有個x參數,把x值丟進去後會回傳42 + x的結果。
第二點,如果toHaveBeenCalledWith()這裡面的數字被調用過,那就是pass(因為是使用指定的參數)。

監測

這裡使用jest.spyOn來達到效果

1
2
3
4
5
6
7
8
9
10
11
12
13
test('spying on method of an object', () => {
const vedio = {
play(){
return true;
},
};

const spy = jest.spyOn(vedio, 'play');
vedio.play();

expect(spy).toHaveBeenCalled();
spy.mockRestore();
})

我們建立了vedio這個function,裡面有個play函式,如果使用了則返回true
這個spy監聽了vedio裡面的play函式。
如果這個paly被調用過,那這裡就會pass
spy.mockRestore(),如果被調用過,則恢復到原始狀態,不會對後續的測試產生影響。

簡單來說,還有許多的地方沒深究,還是得花點時間。