Skip to content

Commit c7e9019

Browse files
committed
test: 레포지토리 통합테스트코드 구현
1 parent 4fd26ac commit c7e9019

File tree

1 file changed

+148
-0
lines changed

1 file changed

+148
-0
lines changed
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import dotenv from 'dotenv';
2+
import { Pool } from 'pg';
3+
import pg from 'pg';
4+
import { DBError } from '@/exception';
5+
import { QRLoginTokenRepository } from '@/repositories/qr.repository';
6+
import { generateRandomToken } from '@/utils/generateRandomToken.util';
7+
import logger from '@/configs/logger.config';
8+
9+
dotenv.config();
10+
jest.setTimeout(30000);
11+
12+
describe('QRLoginTokenRepository 통합 테스트', () => {
13+
let testPool: Pool;
14+
let repo: QRLoginTokenRepository;
15+
16+
const TEST_DATA = {
17+
USER_ID: 1,
18+
};
19+
20+
beforeAll(async () => {
21+
const testPoolConfig: pg.PoolConfig = {
22+
database: process.env.DATABASE_NAME,
23+
user: process.env.POSTGRES_USER,
24+
host: process.env.POSTGRES_HOST,
25+
password: process.env.POSTGRES_PASSWORD,
26+
port: Number(process.env.POSTGRES_PORT),
27+
max: 1,
28+
idleTimeoutMillis: 30000,
29+
connectionTimeoutMillis: 5000,
30+
allowExitOnIdle: false,
31+
statement_timeout: 30000,
32+
};
33+
34+
if (process.env.POSTGRES_HOST !== 'localhost') {
35+
testPoolConfig.ssl = { rejectUnauthorized: false };
36+
}
37+
38+
testPool = new Pool(testPoolConfig);
39+
40+
await testPool.query('SELECT 1');
41+
logger.info('테스트 DB 연결 성공');
42+
43+
repo = new QRLoginTokenRepository(testPool);
44+
});
45+
46+
afterAll(async () => {
47+
try {
48+
await new Promise(resolve => setTimeout(resolve, 1000));
49+
if (testPool) {
50+
await testPool.end();
51+
}
52+
await new Promise(resolve => setTimeout(resolve, 1000));
53+
logger.info('테스트 DB 연결 종료');
54+
} catch (error) {
55+
logger.error('테스트 종료 중 오류:', error);
56+
}
57+
});
58+
59+
describe('QR 토큰 생성 및 조회', () => {
60+
it('QR 토큰을 생성하고 정상 조회할 수 있어야 한다', async () => {
61+
const token = generateRandomToken();
62+
const ip = '127.0.0.1';
63+
const userAgent = 'test-agent';
64+
65+
await repo.createQRLoginToken(token, TEST_DATA.USER_ID, ip, userAgent);
66+
const foundToken = await repo.findQRLoginToken(token);
67+
68+
expect(foundToken).not.toBeNull();
69+
expect(foundToken?.token).toBe(token);
70+
expect(foundToken?.is_used).toBe(false);
71+
expect(new Date(foundToken!.expires_at).getTime()).toBeGreaterThan(new Date(foundToken!.created_at).getTime());
72+
});
73+
74+
it('존재하지 않는 토큰 조회 시 null을 반환해야 한다', async () => {
75+
const invalidToken = generateRandomToken();
76+
const result = await repo.findQRLoginToken(invalidToken);
77+
78+
expect(result).toBeNull();
79+
});
80+
});
81+
82+
describe('QR 토큰 사용 처리', () => {
83+
it('QR 토큰을 사용 처리한 후 조회되지 않아야 한다', async () => {
84+
const token = generateRandomToken();
85+
const ip = '127.0.0.1';
86+
const userAgent = 'test-agent';
87+
88+
await repo.createQRLoginToken(token, TEST_DATA.USER_ID, ip, userAgent);
89+
await repo.markTokenUsed(token);
90+
91+
const found = await repo.findQRLoginToken(token);
92+
93+
expect(found).toBeNull();
94+
});
95+
});
96+
97+
describe('QR 토큰 만료 처리', () => {
98+
it('만료된 토큰은 조회되지 않아야 한다', async () => {
99+
const token = generateRandomToken();
100+
const ip = '127.0.0.1';
101+
const userAgent = 'test-agent';
102+
103+
await testPool.query(
104+
`
105+
INSERT INTO users_qrlogintoken (token, user_id, created_at, expires_at, is_used, ip_address, user_agent)
106+
VALUES ($1, $2, NOW() - INTERVAL '10 minutes', NOW() - INTERVAL '5 minutes', false, $3, $4)
107+
`,
108+
[token, TEST_DATA.USER_ID, ip, userAgent]
109+
);
110+
111+
const found = await repo.findQRLoginToken(token);
112+
113+
expect(found).toBeNull();
114+
});
115+
116+
it('만료되고 사용된 토큰도 조회되지 않아야 한다', async () => {
117+
const token = generateRandomToken();
118+
const ip = '127.0.0.1';
119+
const userAgent = 'test-agent';
120+
121+
await testPool.query(
122+
`
123+
INSERT INTO users_qrlogintoken (token, user_id, created_at, expires_at, is_used, ip_address, user_agent)
124+
VALUES ($1, $2, NOW() - INTERVAL '10 minutes', NOW() - INTERVAL '5 minutes', true, $3, $4)
125+
`,
126+
[token, TEST_DATA.USER_ID, ip, userAgent]
127+
);
128+
129+
const found = await repo.findQRLoginToken(token);
130+
131+
expect(found).toBeNull();
132+
});
133+
});
134+
135+
describe('예외 상황', () => {
136+
it('중복 토큰 삽입 시 DBError를 발생시켜야 한다', async () => {
137+
const token = generateRandomToken();
138+
const ip = '127.0.0.1';
139+
const userAgent = 'test-agent';
140+
141+
await repo.createQRLoginToken(token, TEST_DATA.USER_ID, ip, userAgent);
142+
143+
await expect(
144+
repo.createQRLoginToken(token, TEST_DATA.USER_ID, ip, userAgent)
145+
).rejects.toThrow(DBError);
146+
});
147+
});
148+
});

0 commit comments

Comments
 (0)