在这篇博文中,我们将探讨使用 Jest 和 SuperTest 测试 GraphQL API 所涉及的挑战和解决方案。这个旅程始于需要在 Jest 测试中模拟标头,特别是基于令牌的身份验证。
在为 Woovi 挑战开发 Todo 后端 GraphQL 项目时,我遇到了一个重大障碍。我需要测试 GraphQL API 的身份验证,该身份验证依赖于 HTTP 标头中传递的 JSON Web 令牌 (JWT)。最初,我努力寻找一种直接的方法来在 Jest 中模拟这些标头。标准 Jest 设置还不够,因为它没有像真实服务器那样直接处理 HTTP 请求和响应。
经过多次尝试和错误,我遇到了 SuperTest,一个专为 HTTP 断言设计的库。 SuperTest 允许您像测试真实客户端一样测试 HTTP 服务器,从而扩展了 Jest 的功能。此功能使得模拟标头成为可能,包括我的 API 身份验证所需的授权令牌。
在进行测试之前,让我们先设置环境。
npm install --save-dev jest supertest faker
module.exports = { preset: 'ts-jest', testEnvironment: 'node', };
SuperTest 成为了这种情况下的游戏规则改变者。以下是我如何使用它来测试 API 的 CRUD 操作和身份验证。
import { connect, disconnectDatabase } from './mongooseConnection'; import supertest from 'supertest'; import app from './../index'; beforeAll(async () => { await connect(); }); afterAll(async () => { await disconnectDatabase(); });
import { faker } from '@faker-js/faker'; import { graphql } from 'graphql'; import { schema } from '../schema'; async function authUserTest() { const userTest = { name: faker.name.firstName(), email: faker.internet.email(), password: faker.internet.password(), }; const source = ` mutation { register(name: "${userTest.name}", email: "${userTest.email}", password: "${userTest.password}") { token user { name email } } } `; const result = await graphql({ schema, source }); const data = result.data?.register; return data.token; }
测试任务 CRUD 操作
it('should create a new task', async () => { const todo = { task: faker.lorem.words(), status: faker.helpers.arrayElement(['pending', 'complete', 'in progress']), }; const query = ` mutation { todo(task: "${todo.task}", status: "${todo.status}") { task status } } `; const { body } = await supertest(app) .post('/graphql') .send({ query }) .set('Accept', 'application/json') .set('Authorization', `Bearer ${await authUserTest()}`); expect(body.data.todo).toMatchObject(todo); });
检索所有任务
it('should retrieve all tasks', async () => { const query = ` query { todos { _id task status } } `; const { body } = await supertest(app) .post('/graphql') .send({ query }) .set('Accept', 'application/json') .set('Authorization', `Bearer ${await authUserTest()}`); expect(body.data.todos).toBeInstanceOf(Array); });
更新任务
it('should update a task', async () => { const todos = await Todo.find(); const randomTodo = todos[Math.floor(Math.random() * todos.length)]; const updatedTask = faker.lorem.words(); const updatedStatus = faker.helpers.arrayElement(['pending', 'complete', 'in progress']); const query = ` mutation { updateTodo(_id: "${randomTodo._id}", task: "${updatedTask}", status: "${updatedStatus}") { task status } } `; const { body } = await supertest(app) .post('/graphql') .send({ query }) .set('Accept', 'application/json') .set('Authorization', `Bearer ${await authUserTest()}`); expect(body.data.updateTodo.task).toBe(updatedTask); expect(body.data.updateTodo.status).toBe(updatedStatus); });
删除任务
it('should delete a task', async () => { const todos = await Todo.find(); const randomTodo = todos[Math.floor(Math.random() * todos.length)]; const query = ` mutation { deleteTodo(_id: "${randomTodo._id}") { _id } } `; const { body } = await supertest(app) .post('/graphql') .send({ query }) .set('Accept', 'application/json') .set('Authorization', `Bearer ${await authUserTest()}`); expect(body.data.deleteTodo._id).toBe(randomTodo._id); });
使用 Jest 运行测试:
npm test
此命令将执行所有测试文件,并提供详细的结果报告。
在 Jest 中模拟 header 的困难导致了 SuperTest 的发现,它大大简化了过程。通过利用 SuperTest 和 Jest,我能够有效地测试 GraphQL API 的身份验证和 CRUD 操作,确保应用程序的安全性和功能。分享这个学习过程突显了公共学习和社区驱动的问题解决的力量。
以上是使用 Jest 和 SuperTest 测试 GraphQL 应用程序的详细内容。更多信息请关注PHP中文网其他相关文章!