1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【NestJS】GraphQL初心者がテストを書こうとしたら詰まった

Last updated at Posted at 2022-04-11

結論

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側の仕様の話だったので、もっとちゃんとドキュメント読もうねという話だった。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?