NestJs Chapter 6 (Jest)

yeopยท2022๋…„ 7์›” 20์ผ

Nest JS ์ •๋ฆฌ

๋ชฉ๋ก ๋ณด๊ธฐ
6/10

End To End Testing

๐Ÿ”ท SetUp

Jest did not exit one second after the test run has completed.์™€ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ๋œฌ๋‹ค๋ฉด app.close()๋ฅผ ํ†ตํ•ด ํ…Œ์ŠคํŠธ๊ฐ€ ๋๋‚˜๊ณ  ๋‚œ ํ›„, app์„ ์ข…๋ฃŒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.

afterAll(async () => {
await app.close();
});

๐Ÿ”น Connection

Connection์€ ํŠน์ • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋Œ€ํ•œ ๋‹จ์ผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ORM ์—ฐ๊ฒฐ.
์›๋ž˜๋Š” getConnection()์ด๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด Connection์„ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ Deprecated๋œ ์ดํ›„์—๋Š” ์•„๋ž˜์˜ afterAll ๋ถ€๋ถ„์˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด ์ž‘์„ฑํ•ด์•ผํ•œ๋‹ค.

๐Ÿ”นdropDatabase()

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์ด ์™„๋ฃŒ๋œ ํ›„์—๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. test๊ฐ€ ๋๋‚œ ํ›„์— test๋ฅผ ์œ„ํ•ด ์ƒ์„ฑํ–ˆ๋˜ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ญ์ œํ•ด์ฃผ๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค.

/* eslint-disable prettier/prettier */
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import { AppModule } from '../src/app.module';
import { DataSource } from 'typeorm';

const GRAPHQL_ENDPOINT = '/graphql';

const testUser = {
  email: 'yeop@naver.com',
  password: '12345',
};

jest.mock('got', () => {
  return {
    post: jest.fn(),
  };
});

describe('AppController (e2e)', () => {
  let app: INestApplication;

  beforeAll(async () => {
    const module: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = module.createNestApplication();
    await app.init();
  });

  afterAll(async () => {
    const dataSource = new DataSource({
      type: 'postgres',
      host: 'localhost',
      port: 5432,
      username: 'juyeop',
      password: '12345',
      database: 'nuber-eats-test',
    });
    const connection = await dataSource.initialize();
    await connection.dropDatabase();
    await connection.destroy();
    app.close();
  });

  it.todo('can createAccount');
  it.todo('userProfile');
  it.todo('login');
  it.todo('me');
  it.todo('verifyEmail');
  it.todo('userEdit');
});

๐Ÿ”ท Resolvers Testing

๐Ÿ”น--detectOpenHandles

"Jest did not exit one second after the test run has completed.

This usually means that there are asynchronous operations that weren't stopped in your tests. Consider running Jest with --detectOpenHandles to troubleshoot this issue. "

์ด์™€ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ package.json์— --detectOpenHandles๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ์–ด๋А ๋ถ€๋ถ„์ด asynchronous operations that weren't stopped ์ธ์ง€ ์•Œ๋ ค์ค€๋‹ค.

์ด๋ฒˆ ๊ฒฝ์šฐ์—๋Š” got moudule์—์„œ ์—๋Ÿฌ๊ฐ€ ๋‚ฌ์œผ๋ฉฐ ์ด๋ฅผ ๊ณ ์น˜๊ธฐ ์œ„ํ•ด got.post๋ฅผ mockํ•จ์ˆ˜๋กœ ๋งŒ๋“ค์—ˆ๋‹ค.

๐Ÿ”น Login Mutation

describe('login', () => {
    it('Should login with correct credentials', () => {
      return request(app.getHttpServer())
        .post(GRAPHQL_ENDPOINT)
        .send({
          query: `
          mutation {
            login(input:{
              email:"${testUser.email}",
              password:"${testUser.password}",
            }) {
              ok
              error
              token
            }
          }
        `,
        })
        .expect(200)
        .expect((res) => {
          const {
            body: {
              data: { login },
            },
          } = res;
          expect(login.ok).toEqual(true);
          expect(login.error).toEqual(null);
          expect(login.token).toEqual(expect.any(String));
          jwtToken = login.token;
        });
    });
  });

๐Ÿ”น UserProfile

  • userId๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด์„œ๋Š” user ํ…Œ์ด๋ธ”์˜ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์™€์•ผํ•˜๋Š”๋ฐ ์ด๋Š” ๋ชจ๋“ˆ์„ ํ†ตํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.
usersRepository = module.get<Repository<User>>(getRepositoryToken(User));

๋˜ํ•œ superTest๋กœ request๋ฅผ ๋ณด๋‚ผ ๋•Œ, .post() ๋‹ค์Œ .set()์„ ์ด์šฉํ•ด์„œ http header๋ฅผ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

describe('userProfile', () => {
    let userId: number;
    beforeAll(async () => {
      const [user] = await usersRepository.find();
      userId = user.id;
    });
    it("Should see a User's Profile", () => {
      return request(app.getHttpServer())
        .post(GRAPHQL_ENDPOINT)
        .set('X-JWT', jwtToken)
        .send({
          query: `
          {
          userProfile(userId:${userId}){
            ok
            error
            user {
              id
            }
          }
        }
          `,
        })
        .expect(200)
        .expect((res) => {
          const {
            body: {
              data: {
                userProfile: {
                  ok,
                  error,
                  user: { id },
                },
              },
            },
          } = res;
          expect(ok).toEqual(true);
          expect(error).toEqual(null);
          expect(id).toEqual(userId);
        });
    });

0๊ฐœ์˜ ๋Œ“๊ธ€