このブログ投稿では、Jest と SuperTest を使用して GraphQL API をテストする際の課題と解決策を検討します。この取り組みは、Jest テストでヘッダー、特にトークンベースの認証をシミュレートする必要があることから始まりました。
Woovi チャレンジ用の Todo バックエンド GraphQL プロジェクトを開発しているときに、重大な障害に遭遇しました。 HTTP ヘッダーで渡される JSON Web Token (JWT) に依存する GraphQL API の認証をテストする必要がありました。当初、私は Jest でこれらのヘッダーをシミュレートする簡単な方法を見つけるのに苦労しました。標準の Jest セットアップでは、実際のサーバーと同じ方法で HTTP リクエストとレスポンスを直接処理できないため、十分ではありませんでした。
何度か試行錯誤した結果、HTTP アサーション用に設計されたライブラリである SuperTest に行き着きました。 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 でヘッダーをシミュレートするのは難しいため、プロセスを大幅に簡素化する SuperTest が発見されました。 Jest と SuperTest を併用することで、GraphQL API の認証と CRUD 操作を効果的にテストし、アプリケーションのセキュリティと機能を確保することができました。この学習プロセスを共有することで、公開学習とコミュニティ主導の問題解決の力が強調されます。
以上がJest と SuperTest を使用した GraphQL アプリケーションのテストの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。