有時候咱們須要不發送請求就能完成前端的業務邏輯測試,而許多的業務邏輯都會須要調用到後端的API接口。那如何能mock咱們所須要的data就是一個問題。當咱們能有一個良好的測試環境以後,只要保證後端的接口沒有問題,那咱們就能夠保證業務邏輯也沒有問題。javascript
因此咱們對API的集成測試有如下幾個要求前端
1.不發送請求,返回本地假數據java
2.發佈前經過CI跑unit test,經過則發佈上線git
首先通常咱們在network部分都會進行封裝,假設在project中封裝了以下的請求工具github
// http tool
export default function http() {
// some implement
}
複製代碼
既然咱們不能發送真實請求,那咱們就須要相似能攔截的東西,攔截也能夠經過mock代替。因而咱們能夠經過jest.mock
方法來作。後端
// api/http.js
// real fn
export default function http() {
console.log('real');
//...
}
複製代碼
// api/__mocks__/http.js
// fake fn
export default function http() {
console.log('fake');
}
複製代碼
// some.test.js
jest.mock('../http')
import http from '../http'
http() // 這裏log的是fake,而不是real
複製代碼
這個就是jest.mock
的做用。api
明白了這個後就好辦了。項目目錄以下:安全
-- api
|-- __mockData__
|-- user.data.js
|-- __mocks__
|-- http.js
|-- __tests__
|-- user.test.js
|-- http.js
|-- profile // profile 業務模塊
|-- user.js // 獲取用戶信息
複製代碼
而咱們的fake文件其實主要作的事情就是根據請求url,method,status等,去讀取對應的本地假數據。大體以下。數據結構
// ./api/__mocks__/http.js
// 直接讀取本地假數據
let statusCode;
export function setStatus(code) {
statusCode = code;
}
export default function http({ url = "", data = {}, method = "get" }) {
return new Promise((resolve, reject) => {
const lastSlash = url.lastIndexOf("/");
const module = url.substring(lastSlash + 1);
const mockData = require(`../__mockData__/${module}.data`).default;
const result = mockData[`${method.toUpperCase()} ${statusCode}`];
process.nextTick(
() => (statusCode === 200 ? resolve(result) : reject(result))
);
});
}
複製代碼
mockData文件夾則就是放咱們的假數據,在這咱們能夠假設定義以下數據結構,來模擬咱們的responseasync
// ./api/__mockData__/user.js
export default {
'GET 200': {
code: 0,
msg: 'ok',
data: {
username: '二哲',
age: 18,
},
},
'POST 200': {
code: 0,
msg: 'xxx',
},
'GET 400': {
msg: 'invald params',
code: -1,
},
'GET 401': {},
};
複製代碼
最後看下咱們的 unit test 如何寫
// ./api/__test__/user.test.js
jest.mock('../http') // jest 會自動搜索目錄下的 __mocks__裏的文件
import http from '../http';
describe('user api test', () => {
it("user GET should be 200", async () => {
setStatus(200);
const result = await http({
url,
method: "get"
});
expect(result.data.username).toBe("Kodo");
});
})
複製代碼
假設/user
接口返回得數據多是這樣
{
"username": "二哲",
"age": 18,
}
複製代碼
而咱們前端service層爲UI層提供了一個initUserData的方法,initUserData方法裏的操做是當age
爲18,那就要返回19。
因此咱們在Jest則能夠直接這樣測試
// ./api/__test__/user.test.js
jest.mock('../http') // jest 會自動搜索目錄下的 __mocks__裏的文件
import { setStatus } from './http';
import { initUserData } from '../user'
describe('user api test', () => {
it("if user age is 18, age should be 19", async () => {
expect.assertions(1);
setStatus(200);
const result = await initUserData();
// console.log(result);
expect(result.data.age).toBe(19);
});
// test catch
it("initUserData 400", async () => {
expect.assertions(1);
setStatus(400);
const result = await initUserData();
expect(result.msg).toBe("invald params");
});
})
複製代碼
這樣咱們使用Jest就能夠完成對業務邏輯的測試,Unit test在大型項目中很是須要,每當提交一個feature時,能夠跑完全部測試,會讓你很是有安全感,極大提高了項目的穩定性。
真正的方法(http),與mock的方法http,文件必須同名,而後放在mocks文件夾下便可。若是不一樣名使用jest.mock()則會失敗。
以上例子都在這 jest-api-test