【架构师(第四十三篇)】 服务端开发之单元测试和接口测试

Jest

安装

npm i jest --save-dev

测试 demo

// __test__\demo.test.js

describe('test demo', () => {
  test('1 + 1 = 2', () => {
    expect(1 + 1).toBe(2)
  })
})

控制台执行 npm run test:local

添加测试命令

// package.json

  "scripts": {
    "test:local": "cross-env NODE_ENV=test_local jest --runInBand  --passWithNoTests --colors --forceExit",
  },

image.png

supertest 接口测试

有接口测试的保护,让所有接口稳如老狗,哈哈。

安装

本地测试

jest + supertest

远程测试

jest + axios

和单元测试的关系

接口测试和单元测试,代码都放在 __test__ 目录下,但两者概念要区分开。

代码演示

  • 安装 supertestaxios
  • package.json 添加 test:remote 命令
  • 接口测试代码目录 __test__/apis/

安装插件

npm i  axios supertest -S

添加测试命令

// package.json

  "scripts": {
    "test:local": "cross-env NODE_ENV=test_local jest --runInBand  --passWithNoTests --colors --forceExit",
    "test:remote": "cross-env NODE_ENV=test_remote jest --runInBand  --passWithNoTests --colors --forceExit"
  },

封装请求

// __test__\apis\_server.js

const axios = require('axios')
const supertest = require('supertest')
const { isTestRemote, isTestLocal } = require('../../src/utils/env')

let request
if (isTestLocal) {
  // 本地测试才使用 supertest 。src/app 也要在此时引用,否则在 github actions 中初始化时,会报数据库连接错误。
  const server = require('../../src/app').callback() // eslint-disable-line
  request = supertest(server)
}

// 存储登录 token ,统一拼接 headers.Authorization
let TOKEN = ''

// 测试机 host
const REMOTE_HOST = 'http://182.92.xxx.xxx:8081'

/**
 * 发送请求
 * @param {string} method method
 * @param {string} url url
 * @param {object} bodyOrParams body / query
 * @param {object} headers headers
 */
async function ajax(method = 'get', url = '', bodyOrParams = {}, headers = {}) {
  // headers 加 token
  if (headers.Authorization == null) {
    Object.assign(headers, {
      Authorization: `Bearer ${TOKEN}`,
    })
  }

  let result

  // 本地测试,使用 supertest
  if (isTestLocal) {
    let res
    if (method === 'get') {
      res = await request[method](url).query(bodyOrParams).set(headers)
    } else {
      res = await request[method](url).send(bodyOrParams).set(headers)
    }
    result = res.body
  }

  // 远程测试,使用 axios ,访问测试机
  if (isTestRemote) {
    const remoteUrl = `${REMOTE_HOST}${url}`
    const conf = {
      method,
      url: remoteUrl,
      headers,
    }
    if (method === 'get') {
      conf.params = bodyOrParams
    } else {
      conf.data = bodyOrParams
    }
    const res = await axios(conf)
    result = res.data
  }

  // 返回结果
  return result // { data, errno }
}

module.exports = {
  setToken(token) {
    console.log('setToken...', token)
    TOKEN = token
  },
  async get(url, params) {
    const res = await ajax('get', url, params)
    return res
  },
  async post(url, body) {
    const res = await ajax('post', url, body)
    return res
  },
  async patch(url, body) {
    const res = await ajax('patch', url, body)
    return res
  },
  async del(url, body) {
    const res = await ajax('delete', url, body)
    return res
  },
}

写接口测试用例

// __test__\apis\db-check.js

// 获取 get 请求
const { get } = require('./_server')

test('数据库连接', async () => {

  // 获取数据
  const { data, errno } = await get('/api/db-check')

  const { redisConn, mysqlConn, mongodbConn } = data

  expect(errno).toBe(0)
  expect(redisConn).toBe(true)
  expect(mysqlConn).toBe(true)
  expect(mongodbConn).toBe(true)
})

测试入口文件

这个文件就是把所有的接口测试都集成到这里了。

// __test__\apis\index.test.js

require('./db-check')

开始测试

控制台执行 npm run test:local,可以看到单元测试和接口测试全部都通过了。

image.png

猜你喜欢

转载自juejin.im/post/7113514040508284959