@@ -13,6 +13,7 @@ interface MockRedisClient {
13
13
del : jest . Mock ;
14
14
exists : jest . Mock ;
15
15
keys : jest . Mock ;
16
+ scan : jest . Mock ;
16
17
}
17
18
18
19
// Redis 모킹
@@ -45,6 +46,7 @@ describe('RedisCache', () => {
45
46
del : jest . fn ( ) ,
46
47
exists : jest . fn ( ) ,
47
48
keys : jest . fn ( ) ,
49
+ scan : jest . fn ( ) ,
48
50
} ;
49
51
50
52
mockCreateClient = createClient as jest . MockedFunction < typeof createClient > ;
@@ -223,11 +225,7 @@ describe('RedisCache', () => {
223
225
224
226
await redisCache . set ( 'test-key' , testData , 600 ) ;
225
227
226
- expect ( mockClient . setEx ) . toHaveBeenCalledWith (
227
- 'test:cache:test-key' ,
228
- 600 ,
229
- JSON . stringify ( testData )
230
- ) ;
228
+ expect ( mockClient . setEx ) . toHaveBeenCalledWith ( 'test:cache:test-key' , 600 , JSON . stringify ( testData ) ) ;
231
229
} ) ;
232
230
233
231
it ( 'TTL 없이 값을 성공적으로 저장해야 한다 (기본 TTL 사용)' , async ( ) => {
@@ -239,7 +237,7 @@ describe('RedisCache', () => {
239
237
expect ( mockClient . setEx ) . toHaveBeenCalledWith (
240
238
'test:cache:test-key' ,
241
239
300 , // 기본 TTL
242
- JSON . stringify ( testData )
240
+ JSON . stringify ( testData ) ,
243
241
) ;
244
242
} ) ;
245
243
@@ -249,10 +247,7 @@ describe('RedisCache', () => {
249
247
250
248
await redisCache . set ( 'test-key' , testData , 0 ) ;
251
249
252
- expect ( mockClient . set ) . toHaveBeenCalledWith (
253
- 'test:cache:test-key' ,
254
- JSON . stringify ( testData )
255
- ) ;
250
+ expect ( mockClient . set ) . toHaveBeenCalledWith ( 'test:cache:test-key' , JSON . stringify ( testData ) ) ;
256
251
} ) ;
257
252
258
253
it ( '연결되지 않은 상태에서는 저장하지 않아야 한다' , async ( ) => {
@@ -367,32 +362,43 @@ describe('RedisCache', () => {
367
362
368
363
it ( '패턴에 맞는 키들을 성공적으로 삭제해야 한다' , async ( ) => {
369
364
const matchingKeys = [ 'test:cache:key1' , 'test:cache:key2' ] ;
370
- mockClient . keys . mockResolvedValue ( matchingKeys ) ;
365
+ mockClient . scan
366
+ . mockResolvedValueOnce ( { cursor : '10' , keys : matchingKeys } )
367
+ . mockResolvedValueOnce ( { cursor : '0' , keys : [ ] } ) ;
371
368
mockClient . del . mockResolvedValue ( 2 ) ;
372
369
373
370
await redisCache . clear ( 'user:*' ) ;
374
371
375
- expect ( mockClient . keys ) . toHaveBeenCalledWith ( 'test:cache:user:*' ) ;
372
+ expect ( mockClient . scan ) . toHaveBeenCalledWith ( '0' , {
373
+ MATCH : 'test:cache:user:*' ,
374
+ COUNT : 100 ,
375
+ } ) ;
376
376
expect ( mockClient . del ) . toHaveBeenCalledWith ( matchingKeys ) ;
377
377
} ) ;
378
378
379
379
it ( '패턴 없이 모든 키를 삭제해야 한다' , async ( ) => {
380
- const allKeys = [ 'test:cache:key1' , 'test:cache:key2' , 'test:cache:key3' ] ;
381
- mockClient . keys . mockResolvedValue ( allKeys ) ;
382
- mockClient . del . mockResolvedValue ( 3 ) ;
380
+ const allKeys = [ 'test:cache:key1' , 'test:cache:key2' ] ;
381
+ mockClient . scan . mockResolvedValueOnce ( { cursor : '0' , keys : allKeys } ) ;
382
+ mockClient . del . mockResolvedValue ( 2 ) ;
383
383
384
384
await redisCache . clear ( ) ;
385
385
386
- expect ( mockClient . keys ) . toHaveBeenCalledWith ( 'test:cache:*' ) ;
386
+ expect ( mockClient . scan ) . toHaveBeenCalledWith ( '0' , {
387
+ MATCH : 'test:cache:*' ,
388
+ COUNT : 100 ,
389
+ } ) ;
387
390
expect ( mockClient . del ) . toHaveBeenCalledWith ( allKeys ) ;
388
391
} ) ;
389
392
390
393
it ( '매칭되는 키가 없는 경우 삭제하지 않아야 한다' , async ( ) => {
391
- mockClient . keys . mockResolvedValue ( [ ] ) ;
394
+ mockClient . scan . mockResolvedValue ( { cursor : '0' , keys : [ ] } ) ;
392
395
393
396
await redisCache . clear ( 'non-existent:*' ) ;
394
397
395
- expect ( mockClient . keys ) . toHaveBeenCalledWith ( 'test:cache:non-existent:*' ) ;
398
+ expect ( mockClient . scan ) . toHaveBeenCalledWith ( '0' , {
399
+ MATCH : 'test:cache:non-existent:*' ,
400
+ COUNT : 100 ,
401
+ } ) ;
396
402
expect ( mockClient . del ) . not . toHaveBeenCalled ( ) ;
397
403
} ) ;
398
404
@@ -403,12 +409,12 @@ describe('RedisCache', () => {
403
409
404
410
await redisCache . clear ( 'test:*' ) ;
405
411
406
- expect ( mockClient . keys ) . not . toHaveBeenCalled ( ) ;
412
+ expect ( mockClient . scan ) . not . toHaveBeenCalled ( ) ;
407
413
expect ( mockClient . del ) . not . toHaveBeenCalled ( ) ;
408
414
} ) ;
409
415
410
416
it ( 'Redis 에러 발생 시 조용히 실패해야 한다' , async ( ) => {
411
- mockClient . keys . mockRejectedValue ( new Error ( 'Redis error' ) ) ;
417
+ mockClient . scan . mockRejectedValue ( new Error ( 'Redis error' ) ) ;
412
418
413
419
await expect ( redisCache . clear ( 'test:*' ) ) . resolves . not . toThrow ( ) ;
414
420
} ) ;
@@ -421,17 +427,23 @@ describe('RedisCache', () => {
421
427
} ) ;
422
428
423
429
it ( '캐시 크기를 올바르게 반환해야 한다' , async ( ) => {
424
- const keys = [ 'test:cache:key1' , 'test:cache:key2' , 'test:cache:key3' ] ;
425
- mockClient . keys . mockResolvedValue ( keys ) ;
430
+ const keys1 = [ 'test:cache:key1' , 'test:cache:key2' ] ;
431
+ const keys2 = [ 'test:cache:key3' ] ;
432
+ mockClient . scan
433
+ . mockResolvedValueOnce ( { cursor : '10' , keys : keys1 } )
434
+ . mockResolvedValueOnce ( { cursor : '0' , keys : keys2 } ) ;
426
435
427
436
const result = await redisCache . size ( ) ;
428
437
429
- expect ( mockClient . keys ) . toHaveBeenCalledWith ( 'test:cache:*' ) ;
438
+ expect ( mockClient . scan ) . toHaveBeenCalledWith ( '0' , {
439
+ MATCH : 'test:cache:*' ,
440
+ COUNT : 100 ,
441
+ } ) ;
430
442
expect ( result ) . toBe ( 3 ) ;
431
443
} ) ;
432
444
433
445
it ( '빈 캐시의 크기는 0이어야 한다' , async ( ) => {
434
- mockClient . keys . mockResolvedValue ( [ ] ) ;
446
+ mockClient . scan . mockResolvedValue ( { cursor : '0' , keys : [ ] } ) ;
435
447
436
448
const result = await redisCache . size ( ) ;
437
449
@@ -446,11 +458,11 @@ describe('RedisCache', () => {
446
458
const result = await redisCache . size ( ) ;
447
459
448
460
expect ( result ) . toBe ( 0 ) ;
449
- expect ( mockClient . keys ) . not . toHaveBeenCalled ( ) ;
461
+ expect ( mockClient . scan ) . not . toHaveBeenCalled ( ) ;
450
462
} ) ;
451
463
452
464
it ( 'Redis 에러 발생 시 0을 반환해야 한다' , async ( ) => {
453
- mockClient . keys . mockRejectedValue ( new Error ( 'Redis error' ) ) ;
465
+ mockClient . scan . mockRejectedValue ( new Error ( 'Redis error' ) ) ;
454
466
455
467
const result = await redisCache . size ( ) ;
456
468
@@ -460,7 +472,9 @@ describe('RedisCache', () => {
460
472
461
473
describe ( '이벤트 핸들러' , ( ) => {
462
474
it ( '연결 이벤트 시 상태를 업데이트해야 한다' , ( ) => {
463
- const connectCall = mockClient . on . mock . calls . find ( ( call : [ string , ( ...args : unknown [ ] ) => void ] ) => call [ 0 ] === 'connect' ) ;
475
+ const connectCall = mockClient . on . mock . calls . find (
476
+ ( call : [ string , ( ...args : unknown [ ] ) => void ] ) => call [ 0 ] === 'connect' ,
477
+ ) ;
464
478
const connectHandler = connectCall ?. [ 1 ] ;
465
479
466
480
expect ( connectHandler ) . toBeDefined ( ) ;
@@ -470,12 +484,16 @@ describe('RedisCache', () => {
470
484
471
485
it ( '에러 이벤트 시 상태를 업데이트해야 한다' , ( ) => {
472
486
// 먼저 연결 상태로 만들기
473
- const connectCall = mockClient . on . mock . calls . find ( ( call : [ string , ( ...args : unknown [ ] ) => void ] ) => call [ 0 ] === 'connect' ) ;
487
+ const connectCall = mockClient . on . mock . calls . find (
488
+ ( call : [ string , ( ...args : unknown [ ] ) => void ] ) => call [ 0 ] === 'connect' ,
489
+ ) ;
474
490
const connectHandler = connectCall ?. [ 1 ] ;
475
491
expect ( connectHandler ) . toBeDefined ( ) ;
476
492
connectHandler ?.( ) ;
477
493
478
- const errorCall = mockClient . on . mock . calls . find ( ( call : [ string , ( ...args : unknown [ ] ) => void ] ) => call [ 0 ] === 'error' ) ;
494
+ const errorCall = mockClient . on . mock . calls . find (
495
+ ( call : [ string , ( ...args : unknown [ ] ) => void ] ) => call [ 0 ] === 'error' ,
496
+ ) ;
479
497
const errorHandler = errorCall ?. [ 1 ] ;
480
498
481
499
expect ( errorHandler ) . toBeDefined ( ) ;
@@ -485,12 +503,16 @@ describe('RedisCache', () => {
485
503
486
504
it ( '연결 해제 이벤트 시 상태를 업데이트해야 한다' , ( ) => {
487
505
// 먼저 연결 상태로 만들기
488
- const connectCall = mockClient . on . mock . calls . find ( ( call : [ string , ( ...args : unknown [ ] ) => void ] ) => call [ 0 ] === 'connect' ) ;
506
+ const connectCall = mockClient . on . mock . calls . find (
507
+ ( call : [ string , ( ...args : unknown [ ] ) => void ] ) => call [ 0 ] === 'connect' ,
508
+ ) ;
489
509
const connectHandler = connectCall ?. [ 1 ] ;
490
510
expect ( connectHandler ) . toBeDefined ( ) ;
491
511
connectHandler ?.( ) ;
492
512
493
- const disconnectCall = mockClient . on . mock . calls . find ( ( call : [ string , ( ...args : unknown [ ] ) => void ] ) => call [ 0 ] === 'disconnect' ) ;
513
+ const disconnectCall = mockClient . on . mock . calls . find (
514
+ ( call : [ string , ( ...args : unknown [ ] ) => void ] ) => call [ 0 ] === 'disconnect' ,
515
+ ) ;
494
516
const disconnectHandler = disconnectCall ?. [ 1 ] ;
495
517
496
518
expect ( disconnectHandler ) . toBeDefined ( ) ;
@@ -499,7 +521,6 @@ describe('RedisCache', () => {
499
521
} ) ;
500
522
} ) ;
501
523
502
-
503
524
describe ( 'private getFullKey' , ( ) => {
504
525
it ( '키에 접두사를 올바르게 추가해야 한다' , async ( ) => {
505
526
mockClient . connect . mockResolvedValue ( undefined ) ;
@@ -523,4 +544,4 @@ describe('RedisCache', () => {
523
544
expect ( mockClient . get ) . toHaveBeenCalledWith ( 'test:cache:' ) ;
524
545
} ) ;
525
546
} ) ;
526
- } ) ;
547
+ } ) ;
0 commit comments