@@ -13,6 +13,7 @@ interface MockRedisClient {
1313 del : jest . Mock ;
1414 exists : jest . Mock ;
1515 keys : jest . Mock ;
16+ scan : jest . Mock ;
1617}
1718
1819// Redis 모킹
@@ -45,6 +46,7 @@ describe('RedisCache', () => {
4546 del : jest . fn ( ) ,
4647 exists : jest . fn ( ) ,
4748 keys : jest . fn ( ) ,
49+ scan : jest . fn ( ) ,
4850 } ;
4951
5052 mockCreateClient = createClient as jest . MockedFunction < typeof createClient > ;
@@ -223,11 +225,7 @@ describe('RedisCache', () => {
223225
224226 await redisCache . set ( 'test-key' , testData , 600 ) ;
225227
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 ) ) ;
231229 } ) ;
232230
233231 it ( 'TTL 없이 값을 성공적으로 저장해야 한다 (기본 TTL 사용)' , async ( ) => {
@@ -239,7 +237,7 @@ describe('RedisCache', () => {
239237 expect ( mockClient . setEx ) . toHaveBeenCalledWith (
240238 'test:cache:test-key' ,
241239 300 , // 기본 TTL
242- JSON . stringify ( testData )
240+ JSON . stringify ( testData ) ,
243241 ) ;
244242 } ) ;
245243
@@ -249,10 +247,7 @@ describe('RedisCache', () => {
249247
250248 await redisCache . set ( 'test-key' , testData , 0 ) ;
251249
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 ) ) ;
256251 } ) ;
257252
258253 it ( '연결되지 않은 상태에서는 저장하지 않아야 한다' , async ( ) => {
@@ -367,32 +362,43 @@ describe('RedisCache', () => {
367362
368363 it ( '패턴에 맞는 키들을 성공적으로 삭제해야 한다' , async ( ) => {
369364 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 : [ ] } ) ;
371368 mockClient . del . mockResolvedValue ( 2 ) ;
372369
373370 await redisCache . clear ( 'user:*' ) ;
374371
375- expect ( mockClient . keys ) . toHaveBeenCalledWith ( 'test:cache:user:*' ) ;
372+ expect ( mockClient . scan ) . toHaveBeenCalledWith ( '0' , {
373+ MATCH : 'test:cache:user:*' ,
374+ COUNT : 100 ,
375+ } ) ;
376376 expect ( mockClient . del ) . toHaveBeenCalledWith ( matchingKeys ) ;
377377 } ) ;
378378
379379 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 ) ;
383383
384384 await redisCache . clear ( ) ;
385385
386- expect ( mockClient . keys ) . toHaveBeenCalledWith ( 'test:cache:*' ) ;
386+ expect ( mockClient . scan ) . toHaveBeenCalledWith ( '0' , {
387+ MATCH : 'test:cache:*' ,
388+ COUNT : 100 ,
389+ } ) ;
387390 expect ( mockClient . del ) . toHaveBeenCalledWith ( allKeys ) ;
388391 } ) ;
389392
390393 it ( '매칭되는 키가 없는 경우 삭제하지 않아야 한다' , async ( ) => {
391- mockClient . keys . mockResolvedValue ( [ ] ) ;
394+ mockClient . scan . mockResolvedValue ( { cursor : '0' , keys : [ ] } ) ;
392395
393396 await redisCache . clear ( 'non-existent:*' ) ;
394397
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+ } ) ;
396402 expect ( mockClient . del ) . not . toHaveBeenCalled ( ) ;
397403 } ) ;
398404
@@ -403,12 +409,12 @@ describe('RedisCache', () => {
403409
404410 await redisCache . clear ( 'test:*' ) ;
405411
406- expect ( mockClient . keys ) . not . toHaveBeenCalled ( ) ;
412+ expect ( mockClient . scan ) . not . toHaveBeenCalled ( ) ;
407413 expect ( mockClient . del ) . not . toHaveBeenCalled ( ) ;
408414 } ) ;
409415
410416 it ( 'Redis 에러 발생 시 조용히 실패해야 한다' , async ( ) => {
411- mockClient . keys . mockRejectedValue ( new Error ( 'Redis error' ) ) ;
417+ mockClient . scan . mockRejectedValue ( new Error ( 'Redis error' ) ) ;
412418
413419 await expect ( redisCache . clear ( 'test:*' ) ) . resolves . not . toThrow ( ) ;
414420 } ) ;
@@ -421,17 +427,23 @@ describe('RedisCache', () => {
421427 } ) ;
422428
423429 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 } ) ;
426435
427436 const result = await redisCache . size ( ) ;
428437
429- expect ( mockClient . keys ) . toHaveBeenCalledWith ( 'test:cache:*' ) ;
438+ expect ( mockClient . scan ) . toHaveBeenCalledWith ( '0' , {
439+ MATCH : 'test:cache:*' ,
440+ COUNT : 100 ,
441+ } ) ;
430442 expect ( result ) . toBe ( 3 ) ;
431443 } ) ;
432444
433445 it ( '빈 캐시의 크기는 0이어야 한다' , async ( ) => {
434- mockClient . keys . mockResolvedValue ( [ ] ) ;
446+ mockClient . scan . mockResolvedValue ( { cursor : '0' , keys : [ ] } ) ;
435447
436448 const result = await redisCache . size ( ) ;
437449
@@ -446,11 +458,11 @@ describe('RedisCache', () => {
446458 const result = await redisCache . size ( ) ;
447459
448460 expect ( result ) . toBe ( 0 ) ;
449- expect ( mockClient . keys ) . not . toHaveBeenCalled ( ) ;
461+ expect ( mockClient . scan ) . not . toHaveBeenCalled ( ) ;
450462 } ) ;
451463
452464 it ( 'Redis 에러 발생 시 0을 반환해야 한다' , async ( ) => {
453- mockClient . keys . mockRejectedValue ( new Error ( 'Redis error' ) ) ;
465+ mockClient . scan . mockRejectedValue ( new Error ( 'Redis error' ) ) ;
454466
455467 const result = await redisCache . size ( ) ;
456468
@@ -460,7 +472,9 @@ describe('RedisCache', () => {
460472
461473 describe ( '이벤트 핸들러' , ( ) => {
462474 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+ ) ;
464478 const connectHandler = connectCall ?. [ 1 ] ;
465479
466480 expect ( connectHandler ) . toBeDefined ( ) ;
@@ -470,12 +484,16 @@ describe('RedisCache', () => {
470484
471485 it ( '에러 이벤트 시 상태를 업데이트해야 한다' , ( ) => {
472486 // 먼저 연결 상태로 만들기
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+ ) ;
474490 const connectHandler = connectCall ?. [ 1 ] ;
475491 expect ( connectHandler ) . toBeDefined ( ) ;
476492 connectHandler ?.( ) ;
477493
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+ ) ;
479497 const errorHandler = errorCall ?. [ 1 ] ;
480498
481499 expect ( errorHandler ) . toBeDefined ( ) ;
@@ -485,12 +503,16 @@ describe('RedisCache', () => {
485503
486504 it ( '연결 해제 이벤트 시 상태를 업데이트해야 한다' , ( ) => {
487505 // 먼저 연결 상태로 만들기
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+ ) ;
489509 const connectHandler = connectCall ?. [ 1 ] ;
490510 expect ( connectHandler ) . toBeDefined ( ) ;
491511 connectHandler ?.( ) ;
492512
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+ ) ;
494516 const disconnectHandler = disconnectCall ?. [ 1 ] ;
495517
496518 expect ( disconnectHandler ) . toBeDefined ( ) ;
@@ -499,7 +521,6 @@ describe('RedisCache', () => {
499521 } ) ;
500522 } ) ;
501523
502-
503524 describe ( 'private getFullKey' , ( ) => {
504525 it ( '키에 접두사를 올바르게 추가해야 한다' , async ( ) => {
505526 mockClient . connect . mockResolvedValue ( undefined ) ;
@@ -523,4 +544,4 @@ describe('RedisCache', () => {
523544 expect ( mockClient . get ) . toHaveBeenCalledWith ( 'test:cache:' ) ;
524545 } ) ;
525546 } ) ;
526- } ) ;
547+ } ) ;
0 commit comments