-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[BE] Auth E2E 테스트 작성 #389
[BE] Auth E2E 테스트 작성 #389
Changes from 9 commits
58609ca
603c64a
26fbe00
b459658
490ada0
5793540
3ca3cd9
9189f04
a2d9bb2
1dc43b3
7a41ac2
7d86a3b
9fe7167
b6c36c9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
import * as request from 'supertest'; | ||
import { INestApplication } from '@nestjs/common'; | ||
import { Test } from '@nestjs/testing'; | ||
import { AppModule } from 'src/app.module'; | ||
import { AuthService } from 'src/auth/auth.service'; | ||
import { testRedisConfig } from 'src/configs/redis.config'; | ||
import Redis from 'ioredis'; | ||
import { DataSource, QueryRunner } from 'typeorm'; | ||
import { UsersRepository } from 'src/users/users.repository'; | ||
import { SocialType } from 'src/users/entity/socialType'; | ||
import { User } from 'src/users/entity/user.entity'; | ||
import * as cookieParser from 'cookie-parser'; | ||
|
||
describe('AuthController (e2e)', () => { | ||
let app: INestApplication; | ||
let authService: AuthService; | ||
let usersRepository: UsersRepository; | ||
let queryRunner: QueryRunner; | ||
const redis = new Redis(testRedisConfig); | ||
|
||
const mockProfile = { | ||
id: '1', | ||
email: 'test@test.com', | ||
nickname: 'testUser', | ||
profile_image: 'testImage', | ||
}; | ||
const mockAccessToken = 'mock token'; | ||
const body = { code: 'code', state: 'state', socialType: 'naver' }; | ||
|
||
beforeAll(async () => { | ||
await redis.flushall(); | ||
const module = await Test.createTestingModule({ | ||
imports: [AppModule], | ||
}).compile(); | ||
|
||
const dataSource = module.get<DataSource>(DataSource); | ||
queryRunner = dataSource.createQueryRunner(); | ||
dataSource.createQueryRunner = jest.fn(); | ||
queryRunner.release = jest.fn(); | ||
(dataSource.createQueryRunner as jest.Mock).mockReturnValue(queryRunner); | ||
|
||
authService = module.get<AuthService>(AuthService); | ||
usersRepository = module.get<UsersRepository>(UsersRepository); | ||
app = module.createNestApplication(); | ||
app.use(cookieParser()); | ||
await app.init(); | ||
|
||
jest.spyOn(authService, <keyof AuthService>'getToken').mockResolvedValue(mockAccessToken); | ||
jest | ||
.spyOn(authService, <keyof AuthService>'getUserProfile') | ||
.mockResolvedValue(mockProfile as any); | ||
HyoJongPark marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}); | ||
|
||
afterAll(async () => { | ||
await redis.quit(); | ||
await app.close(); | ||
}); | ||
|
||
beforeEach(async () => { | ||
await queryRunner.startTransaction(); | ||
}); | ||
|
||
afterEach(async () => { | ||
await redis.flushall(); | ||
await queryRunner.rollbackTransaction(); | ||
}); | ||
|
||
describe('/login (POST)', () => { | ||
HyoJongPark marked this conversation as resolved.
Show resolved
Hide resolved
|
||
beforeAll(() => { | ||
jest.spyOn(usersRepository, 'createUser'); | ||
}); | ||
|
||
afterEach(() => { | ||
(usersRepository.createUser as jest.Mock).mockClear(); | ||
}); | ||
|
||
it('DB에 존재하지 않는 socialId로 로그인 요청이 오면, 회원가입 후 토큰 반환', async () => { | ||
shunny822 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
//given | ||
const url = '/auth/login'; | ||
|
||
//when | ||
const response = await request(app.getHttpServer()).post(url).send(body); | ||
|
||
//then | ||
expect(response.status).toEqual(201); | ||
expect(response.header['set-cookie']).toBeTruthy(); | ||
expect(usersRepository.createUser).toHaveBeenCalled(); | ||
}); | ||
|
||
it('DB에 존재하는 않는 socialId로 로그인 요청이 오면, 회원가입 후 토큰 반환', async () => { | ||
//given | ||
const user = { | ||
id: 1, | ||
email: mockProfile.email, | ||
nickname: mockProfile.nickname, | ||
socialId: mockProfile.id, | ||
socialType: SocialType.NAVER, | ||
profileImage: mockProfile.profile_image, | ||
} as User; | ||
const url = '/auth/login'; | ||
|
||
await usersRepository.save(user); | ||
|
||
//when | ||
const response = await request(app.getHttpServer()).post(url).send(body); | ||
|
||
//then | ||
expect(response.status).toEqual(201); | ||
expect(response.header['set-cookie']).toBeTruthy(); | ||
expect(usersRepository.createUser).not.toHaveBeenCalled(); | ||
}); | ||
}); | ||
|
||
describe('/refresh_token (GET)', () => { | ||
HyoJongPark marked this conversation as resolved.
Show resolved
Hide resolved
|
||
it('유효한 jwt 토큰으로 refresh 요청 시 새 토큰 발급', async () => { | ||
//given | ||
const url = '/auth/refresh_token'; | ||
const agent = request.agent(app.getHttpServer()); | ||
await agent.post('/auth/login').send(body); | ||
|
||
//when | ||
const response = await agent.get(url); | ||
|
||
//then | ||
expect(response.status).toEqual(200); | ||
expect(response.header['set-cookie']).toBeTruthy(); | ||
}); | ||
|
||
it('jwt 없이 refresh 요청 시 401 에러 발생', async () => { | ||
//given | ||
const url = '/auth/refresh_token'; | ||
const agent = request.agent(app.getHttpServer()); | ||
await agent.post('/auth/login').send(body); | ||
|
||
//when | ||
const response = await request(app.getHttpServer()).get(url); | ||
|
||
//then | ||
expect(response.status).toEqual(401); | ||
expect(response.body.message).toEqual('Unauthorized'); | ||
}); | ||
|
||
it('redis에 저장되지 않은 토큰으로 요청 시 401 에러 발생', async () => { | ||
//given | ||
const url = '/auth/refresh_token'; | ||
const agent = request.agent(app.getHttpServer()); | ||
|
||
await agent.post('/auth/login').send(body); | ||
redis.flushall(); | ||
|
||
//when | ||
const response = await agent.get(url); | ||
|
||
//then | ||
expect(response.status).toEqual(401); | ||
expect(response.body.message).toEqual('로그인이 필요합니다.'); | ||
}); | ||
}); | ||
|
||
describe('/logout (POST)', () => { | ||
it('유효한 jwt 토큰으로 logout 요청 시 201 반환', async () => { | ||
//given | ||
const url = '/auth/logout'; | ||
const agent = request.agent(app.getHttpServer()); | ||
|
||
await agent.post('/auth/login').send(body); | ||
|
||
//when | ||
const response = await agent.post(url); | ||
|
||
//then | ||
expect(response.status).toEqual(201); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. logout의 response status가 201로 오던데, 의도하신건가요?? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 호오.. 아니욥ㅋㅋㅋ status code를 바꾸려면 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 좋네요!! 이걸로 200 코드를 반환하도록 변경했습니다. |
||
expect(response.header['set-cookie']).toHaveLength(1); | ||
expect(response.header['set-cookie'][0]).toContain('Max-Age=0;'); | ||
}); | ||
|
||
it('비로그인 사용자가 로그아웃 요청을 보내면 201 반환', async () => { | ||
//given | ||
const url = '/auth/logout'; | ||
|
||
//when | ||
const response = await request(app.getHttpServer()).post(url); | ||
|
||
//then | ||
expect(response.status).toEqual(201); | ||
expect(response.header['set-cookie']).toHaveLength(1); | ||
expect(response.header['set-cookie'][0]).toContain('Max-Age=0;'); | ||
}); | ||
HyoJongPark marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}); | ||
}); |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
기존에 refresh 토큰 발급 기능에서 토큰 없이 요청이 오는 경우 500 에러가 발생해 controller 진입 전 jwt토큰 유효성 검증을 하도록 변경했습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이렇게 하면 이 API를 사용하는 일반적인 경우인,
jwt 토큰이 있지만 유효기한이 지난 경우에 가드에서 계속 막히지 않나요..?
서비스 로직에서 jwt가 없는 경우에 로그인 하도록
UnauthorizedException
을 보내도록 추가해도 좋을 것 같아요!There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
가드는 삭제하고, 서비스 로직에서 체크하도록 변경했습니다