結論
GraphQLは一般的なRESTと違い、httpステータスは200で返してレスポンスのerrorsキーにエラーの情報を入れるのが一般的なので、リクエストが成功したかどうかのテストの際はres.statusで判断してはいけない。
概要
最初 NestJS(driverはApolloDriver) + GraphQL で認証実装後に以下のようにResolverのテストを書いたら、res.status
は200だよってエラーになった。
import { Test, TestingModule } from "@nestjs/testing";
import { INestApplication } from "@nestjs/common";
import * as request from "supertest";
import { HogeModule } from "src/hoge.module";
describe("HogeResolver", () => {
let app: INestApplication;
let HogeService = { findUnique: () => ["test"], findMany: () => ["test2"] };
let resolver: HogeResolver;
beforeAll(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [HogeModule],
})
.overrideProvider(HogeService)
.useValue(HogeService).compile();
resolver = module.get<HogeResolver>(HogeResolver);
app = module.createNestApplication();
await app.init();
});
afterAll(async () => {
await app.close();
});
it("should be defined", () => {
expect(resolver).toBeDefined();
});
it("sample", async () => {
const res = await request(app.getHttpServer())
.post("/graphql")
.send({
query: "{ hoge { edges { node { id } } } }",
})
expect(res.status).toBe(401)
});
});
console.log(res.text)
でresの中身を見ても、
{"errors":[{"message":"Unauthorized","extensions":{"code":"UNAUTHENTICATED","response":{"statusCode":401,"message":"Unauthorized"}}}],"data":null}
となっていて、401エラーのようだったから、なんでres.statusが200なの?????って感じだった。
→それで色々調べてみたら、結論にも書いた通り、RESTとはエラーの返し方が違うみたいで、GraphQLではhttpステータスは200で返してレスポンスのerrorsキーにエラーの情報を入れるのが一般的らしいことがわかった。
なので最終的には以下のようになった。
import { Test, TestingModule } from "@nestjs/testing";
import { INestApplication } from "@nestjs/common";
import * as request from "supertest";
import { HogeModule } from "src/hoge.module";
describe("HogeResolver", () => {
let app: INestApplication;
let HogeService = { findUnique: () => ["test"], findMany: () => ["test2"] };
let resolver: HogeResolver;
beforeAll(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [HogeModule],
})
.overrideProvider(HogeService)
.useValue(HogeService).compile();
resolver = module.get<HogeResolver>(HogeResolver);
app = module.createNestApplication();
await app.init();
});
afterAll(async () => {
await app.close();
});
it("should be defined", () => {
expect(resolver).toBeDefined();
});
it("sample", async () => {
const res = await request(app.getHttpServer())
.post("/graphql")
.send({
query: "{ hoge { edges { node { id } } } }",
})
expect(res.body.errors[0].extensions.response.statusCode).toBe(401);
});
});
備考
今回ORMにprismaを使っているので、let HogeService = { findUnique: () => ["test"], findMany: () => ["test2"] };
となっていますが、ここはORMごとに変わるので注意。
NestJS側というより、GraphQL側の仕様の話だったので、もっとちゃんとドキュメント読もうねという話だった。