Fastify RESTful API 自动化测试实战

随着应用程序逐渐增多,特别是公司和团队越来越大,需要确保代码的质量和可靠性。这就是自动化测试的作用。这篇文章将介绍如何使用 Fastify 和 Jest 编写 RESTful API 的自动化测试用例。

Fastify 是什么?

Fastify 是一个高效、低开销的基于 Node.js 的 Web 框架。

它专注于提供最佳的性能和开发者体验,这得益于使用了许多新的 JavaScript 特性,如 Async/Await、Promise、Generator 等等。

Fastify 还有一个特点是插件机制十分强大,可以让你轻松地扩展其功能。

Jest 是什么?

Jest 是 Facebook 开发的一个 JavaScript 测试框架,功能强大而且易于使用。它旨在为前端开发人员提供一种快捷、直观的测试方案。

Jest 的出现标志着前端测试的新时代的到来,它不仅支持常规的单元测试,还支持快照测试和集成测试等。

RESTful API 自动化测试实战

下面我们将使用 Fastify 和 Jest 编写 RESTful API 自动化测试用例。我们将使用以下的 todo list API:

Method Route Payload Description
POST /todos { "title": "string", "completed": "boolean" } create a new todo
GET /todos/:id get a todo by id
PUT /todos/:id { "title": "string", "completed": "boolean" } update a todo by id
DELETE /todos/:id delete a todo by id
GET /todos ?completed=true/false?limit=number&offset=number get all todos with query

安装 Fastify 和 Jest

首先,我们需要安装 Fastify 和 Jest。

npm install --save-dev fastify jest supertest

其中 supertest 是一个 HTTP 请求库,我们用来测试 HTTP API。

编写 Fastify RESTful API

const fastify = require('fastify')()

// mock todos
const todos = []

// create a new todo
fastify.post('/todos', async (request, reply) => {
  const { title, completed } = request.body
  const todo = { id: todos.length + 1, title, completed }
  todos.push(todo)

  return todo
})

// get a todo by id
fastify.get('/todos/:id', async (request, reply) => {
  const { id } = request.params
  const todo = todos.find((todo) => todo.id === Number(id))

  if (!todo) {
    reply.code(404)
    return { error: 'Not Found' }
  }

  return todo
})

// update a todo by id
fastify.put('/todos/:id', async (request, reply) => {
  const { id } = request.params
  const { title, completed } = request.body
  let todo = todos.find((todo) => todo.id === Number(id))

  if (!todo) {
    reply.code(404)
    return { error: 'Not Found' }
  }

  todo.title = title || todo.title
  todo.completed = completed

  return todo
})

// delete a todo by id
fastify.delete('/todos/:id', async (request, reply) => {
  const { id } = request.params
  const index = todos.findIndex((todo) => todo.id === Number(id))

  if (index === -1) {
    reply.code(404)
    return { error: 'Not Found' }
  }

  todos.splice(index, 1)

  return { success: true }
})

// get all todos with query
fastify.get('/todos', async (request, reply) => {
  const { completed, limit = 10, offset = 0 } = request.query
  const list = todos.filter((todo) => {
    if (completed !== undefined) {
      return todo.completed === (completed === 'true')
    }
    return true
  })
  const total = list.length
  const data = list.slice(offset, Number(offset) + Number(limit))

  return { total, data }
})

if (require.main === module) {
  fastify.listen(3000, (err, address) => {
    if (err) throw err
    console.log(`server listening on ${address}`)
  })
}

module.exports = fastify

编写 Jest 测试用例

首先,我们需要在根目录下新建一个 __tests__ 目录,用来存放测试文件。

__tests__ 目录下创建一个 todos.test.js 文件,并编写测试用例。

const app = require('../app')
const supertest = require('supertest')
const request = supertest.agent(app)

afterAll(async () => {
  await request.close()
})

describe('Test todos API', () => {
  test('POST /todos', async () => {
    const data = { title: 'buy a milk', completed: false }
    const res = await request.post('/todos').send(data).expect(200)

    expect(res.body.title).toEqual(data.title)
    expect(res.body.completed).toEqual(data.completed)
  })

  test('GET /todos/:id', async () => {
    const data = { title: 'buy a milk', completed: false }
    const res1 = await request.post('/todos').send(data).expect(200)
    const res2 = await request.get(`/todos/${res1.body.id}`).expect(200)

    expect(res2.body.title).toEqual(data.title)
    expect(res2.body.completed).toEqual(data.completed)
  })

  test('PUT /todos/:id', async () => {
    const data = { title: 'buy a milk', completed: false }
    const update = { title: 'buy a milk and bread', completed: true }
    const res1 = await request.post('/todos').send(data).expect(200)
    const res2 = await request.put(`/todos/${res1.body.id}`).send(update).expect(200)

    expect(res2.body.title).toEqual(update.title)
    expect(res2.body.completed).toEqual(update.completed)
  })

  test('DELETE /todos/:id', async () => {
    const data = { title: 'buy a milk', completed: false }
    const res1 = await request.post('/todos').send(data).expect(200)
    const res2 = await request.delete(`/todos/${res1.body.id}`).expect(200)

    expect(res2.body.success).toEqual(true)
  })

  test('GET /todos', async () => {
    const data = { title: 'buy a milk', completed: false }
    await request.post('/todos').send(data).expect(200)

    const res1 = await request.get('/todos').expect(200)
    expect(res1.body.total).toEqual(1)
    expect(res1.body.data).toHaveLength(1)

    const res2 = await request.get('/todos?completed=false').expect(200)
    expect(res2.body.total).toEqual(1)
    expect(res2.body.data).toHaveLength(1)

    const res3 = await request.get('/todos?completed=true').expect(200)
    expect(res3.body.total).toEqual(0)
    expect(res3.body.data).toHaveLength(0)
  })
})

运行测试用例

在根目录下的 package.json 中添加以下代码。

{
  "scripts": {
    "test": "jest"
  }
}

然后在终端执行以下命令。

npm test

测试结果如下所示。

总结

在这篇文章中,我们使用 Fastify 和 Jest 编写了一个 todo list 的 RESTful API,并编写了相应的自动化测试用例。通过这个例子,你可以初步了解如何使用 Jest 进行单元测试和集成测试。在实际开发中,自动化测试对于团队的开发效率和代码质量是非常重要的。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6593bb4aeb4cecbf2d85fc96


纠错反馈