From 11aba31fe5a65fbe6c741d248af09c87d7105e15 Mon Sep 17 00:00:00 2001 From: Seongtae Date: Tue, 23 Jan 2024 22:24:28 +0900 Subject: [PATCH 1/4] test: mock mail service --- test/mock/mail-service.mock.ts | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 test/mock/mail-service.mock.ts diff --git a/test/mock/mail-service.mock.ts b/test/mock/mail-service.mock.ts new file mode 100644 index 0000000..6be83c0 --- /dev/null +++ b/test/mock/mail-service.mock.ts @@ -0,0 +1,3 @@ +export const mailServiceMock = { + sendResetPasswordEmail: jest.fn(), +}; From 0c0aede15838933e8749bfd1e2c21ca754603276 Mon Sep 17 00:00:00 2001 From: Seongtae Date: Tue, 23 Jan 2024 22:25:27 +0900 Subject: [PATCH 2/4] test: validate email send success case --- .../post-send-password-reset-email.spec.ts | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 test/auth/post-send-password-reset-email.spec.ts diff --git a/test/auth/post-send-password-reset-email.spec.ts b/test/auth/post-send-password-reset-email.spec.ts new file mode 100644 index 0000000..88dd9fe --- /dev/null +++ b/test/auth/post-send-password-reset-email.spec.ts @@ -0,0 +1,93 @@ +import { CACHE_MANAGER, HttpStatus, INestApplication } from '@nestjs/common'; +import { StartedPostgreSqlContainer } from '@testcontainers/postgresql'; +import { DataSource, Repository } from 'typeorm'; +import { Cache } from 'cache-manager'; +import { User } from '../../src/users/entities/user.entity'; +import { Seeder } from '../seeder/seeder.interface'; +import { UserSeeder } from '../seeder/user.seeder'; +import { getBuilder } from '../common/application-builder'; +import { cacheManagerMock } from '../mock/cache-manager.mock'; +import { customJwtService } from '../../src/auth/jwt/jwt.service'; +import { customJwtServiceMock } from '../mock/custom-jwt-service.mock'; +import { MailService } from '../../src/mail/mail.service'; +import { mailServiceMock } from '../mock/mail-service.mock'; +import * as request from 'supertest'; + +jest.setTimeout(30_000); +describe('[POST] /api/auth/logout', () => { + // Application + let app: INestApplication; + let container: StartedPostgreSqlContainer; // TODO 결합도 낮추기 + let dataSource: DataSource; + let cacheManager: Cache; + let jwtService: customJwtService; + + // Repository + let userRepository: Repository; + + // Seeder + const userSeeder: Seeder = new UserSeeder(); + + // Stub + let userStub: User = userSeeder.generateOne({ id: 1 }); // auto increment이므로 1로 적용. + + beforeAll(async () => { + const { + builder, + container: _container, + dataSource: _dataSource, + } = await getBuilder(); + container = _container; + dataSource = _dataSource; + + const module = await builder + .overrideProvider(DataSource) + .useValue(dataSource) + .overrideProvider(CACHE_MANAGER) + .useValue(cacheManagerMock) + .overrideProvider(customJwtService) + .useValue(customJwtServiceMock) + .overrideProvider(MailService) + .useValue(mailServiceMock) + .compile(); + + app = module.createNestApplication(); + await app.init(); + + userRepository = dataSource.getRepository(User); + cacheManager = app.get(CACHE_MANAGER); + jwtService = app.get(customJwtService); + }); + + beforeEach(async () => { + await dataSource.synchronize(true); + }); + + afterAll(async () => { + await app.close(); + await container.stop(); + }); + + /** + * 1. 이메일 전송에 성공한다. + * 2. 유저가 존재하지 않아 실패한다. + * 3. 유저가 인증되지 않아 실패한다. + */ + + describe('이메일 전송에 성공한다.', () => { + beforeEach(async () => { + userStub = userSeeder.generateOne({ verified: true }); + await userRepository.save(userStub); + }); + + it('빈 응답과 함께 201을 반환한다.', async () => { + const emailParam = userStub.email; + + const { status, body } = await request(app.getHttpServer()).post( + `/auth/send-password-reset-email/${emailParam}`, + ); + + expect(status).toBe(HttpStatus.CREATED); + }); + }); +}); From e3d8f08b28f03f057a0e7f7424c82371b614728a Mon Sep 17 00:00:00 2001 From: Seongtae Date: Tue, 23 Jan 2024 22:25:42 +0900 Subject: [PATCH 3/4] test: validate no user case --- test/auth/post-send-password-reset-email.spec.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/auth/post-send-password-reset-email.spec.ts b/test/auth/post-send-password-reset-email.spec.ts index 88dd9fe..7d82591 100644 --- a/test/auth/post-send-password-reset-email.spec.ts +++ b/test/auth/post-send-password-reset-email.spec.ts @@ -90,4 +90,17 @@ describe('[POST] /api/auth/logout', () => { expect(status).toBe(HttpStatus.CREATED); }); }); + + describe('유저가 존재하지 않아 실패한다.', () => { + it('404 예외를 던진다.', async () => { + const emailParam = 'test@email.com'; + + const { status, body } = await request(app.getHttpServer()).post( + `/auth/send-password-reset-email/${emailParam}`, + ); + + expect(status).toBe(HttpStatus.NOT_FOUND); + expect(body.message).toBe('User not found'); + }); + }); }); From 96be47236c03d0de20708b2c6a12fe24ae0403cc Mon Sep 17 00:00:00 2001 From: Seongtae Date: Tue, 23 Jan 2024 22:27:02 +0900 Subject: [PATCH 4/4] test: validate not verified user case --- .../post-send-password-reset-email.spec.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/auth/post-send-password-reset-email.spec.ts b/test/auth/post-send-password-reset-email.spec.ts index 7d82591..667502e 100644 --- a/test/auth/post-send-password-reset-email.spec.ts +++ b/test/auth/post-send-password-reset-email.spec.ts @@ -103,4 +103,22 @@ describe('[POST] /api/auth/logout', () => { expect(body.message).toBe('User not found'); }); }); + + describe('유저가 인증되지 않아 실패한다.', () => { + beforeEach(async () => { + userStub = userSeeder.generateOne({ verified: false }); + await userRepository.save(userStub); + }); + + it('빈 응답과 함께 201을 반환한다.', async () => { + const emailParam = userStub.email; + + const { status, body } = await request(app.getHttpServer()).post( + `/auth/send-password-reset-email/${emailParam}`, + ); + + expect(status).toBe(HttpStatus.UNAUTHORIZED); + expect(body.message).toBe('User not verified'); + }); + }); });