「CI集成」基於Jest Mock API對業務邏輯集成測試

有時候咱們須要不發送請求就能完成前端的業務邏輯測試,而許多的業務邏輯都會須要調用到後端的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方法來作。後端

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時,能夠跑完全部測試,會讓你很是有安全感,極大提高了項目的穩定性。

TIP

真正的方法(http),與mock的方法http,文件必須同名,而後放在mocks文件夾下便可。若是不一樣名使用jest.mock()則會失敗。

以上例子都在這 jest-api-test

相關文章
相關標籤/搜索