Skip to content

Commit 5cc116f

Browse files
yuchem2claude
andauthored
refactor(shared-kernel): 로거 테스트 대역 공용화 및 HttpTranscriber logger 필수화 (#42)
- spec 13곳에 복사돼 있던 noopLogger/silentLogger를 shared-kernel/testing/noop-logger.ts 하나로 통합 - HttpTranscriber의 fetchFn·logger 기본값 제거: 실제 배선은 항상 둘 다 넘기므로, 누락 시 재시도 경고 로그가 조용히 사라지지 않게 타입으로 막는다 Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 4db3db6 commit 5cc116f

16 files changed

Lines changed: 60 additions & 122 deletions

‎apps/backend/src/mediasoup/infrastructure/mediasoup-router.adapter.spec.ts‎

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
import { RtpCodecCapability, WorkerLogLevel, WorkerLogTag } from 'mediasoup/node/lib/types';
22

3-
import { PinoLoggerAdapter } from '@/shared-kernel/infrastructure/pino-logger.adapter';
4-
import { stub } from '@/shared-kernel/testing/stub';
3+
import { noopLogger } from '@/shared-kernel/testing/noop-logger';
54

65
import { MediasoupRouterAdapter } from './mediasoup-router.adapter';
76
import { MediasoupWorkerPool } from './mediasoup-worker.pool';
87

9-
const noopLogger = stub<PinoLoggerAdapter>({ debug: jest.fn(), info: jest.fn(), warn: jest.fn(), error: jest.fn() });
10-
118
const mediaCodecs = [
129
{ kind: 'audio', mimeType: 'audio/opus', clockRate: 48000, channels: 2 },
1310
{ kind: 'video', mimeType: 'video/VP8', clockRate: 90000 },
@@ -24,7 +21,7 @@ const newWorkerPool = (numWorkers: number) =>
2421
logTags: ['info'] as WorkerLogTag[],
2522
},
2623
},
27-
noopLogger,
24+
noopLogger(),
2825
);
2926

3027
const setup = async (numWorkers: number, participantsPerRouter: number) => {
@@ -33,7 +30,7 @@ const setup = async (numWorkers: number, participantsPerRouter: number) => {
3330
const adapter = new MediasoupRouterAdapter(
3431
pool,
3532
{ participantsPerRouter, mediaCodecs },
36-
noopLogger,
33+
noopLogger(),
3734
);
3835
return {
3936
pool,

‎apps/backend/src/mediasoup/infrastructure/mediasoup-transport.adapter.spec.ts‎

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
import { RtpCodecCapability, WorkerLogLevel, WorkerLogTag } from 'mediasoup/node/lib/types';
22

3-
import { PinoLoggerAdapter } from '@/shared-kernel/infrastructure/pino-logger.adapter';
4-
import { stub } from '@/shared-kernel/testing/stub';
3+
import { noopLogger } from '@/shared-kernel/testing/noop-logger';
54

65
import { MediasoupRouterAdapter } from './mediasoup-router.adapter';
76
import { MediasoupTransportAdapter } from './mediasoup-transport.adapter';
87
import { MediasoupWorkerPool } from './mediasoup-worker.pool';
98

10-
const noopLogger = stub<PinoLoggerAdapter>({ debug: jest.fn(), info: jest.fn(), warn: jest.fn(), error: jest.fn() });
11-
129
const mediaCodecs = [
1310
{ kind: 'audio', mimeType: 'audio/opus', clockRate: 48000, channels: 2 },
1411
{ kind: 'video', mimeType: 'video/VP8', clockRate: 90000 },
@@ -25,7 +22,7 @@ const setup = async () => {
2522
logTags: ['info'] as WorkerLogTag[],
2623
},
2724
},
28-
noopLogger,
25+
noopLogger(),
2926
);
3027
await pool.onModuleInit();
3128
const routerAdapter = new MediasoupRouterAdapter(
@@ -34,7 +31,7 @@ const setup = async () => {
3431
participantsPerRouter: 5,
3532
mediaCodecs,
3633
},
37-
noopLogger,
34+
noopLogger(),
3835
);
3936
const transportAdapter = new MediasoupTransportAdapter(routerAdapter, {
4037
listenIps: [{ ip: '127.0.0.1', announcedIp: '127.0.0.1' }],

‎apps/backend/src/mediasoup/infrastructure/mediasoup-worker.pool.spec.ts‎

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
import { WorkerLogLevel, WorkerLogTag } from 'mediasoup/node/lib/types';
22

3-
import { PinoLoggerAdapter } from '@/shared-kernel/infrastructure/pino-logger.adapter';
4-
import { stub } from '@/shared-kernel/testing/stub';
3+
import { noopLogger } from '@/shared-kernel/testing/noop-logger';
54

65
import { MediasoupWorkerPool } from './mediasoup-worker.pool';
76

8-
const noopLogger = stub<PinoLoggerAdapter>({ debug: jest.fn(), info: jest.fn(), warn: jest.fn(), error: jest.fn() });
9-
107
const baseOptions = (numWorkers: number) => ({
118
numWorkers,
129
worker: {
@@ -19,7 +16,7 @@ const baseOptions = (numWorkers: number) => ({
1916

2017
describe('MediasoupWorkerPool', () => {
2118
it('onModuleInit 후 options.numWorkers 만큼의 살아있는 worker를 보유한다', async () => {
22-
const pool = new MediasoupWorkerPool(baseOptions(1), noopLogger);
19+
const pool = new MediasoupWorkerPool(baseOptions(1), noopLogger());
2320
try {
2421
await pool.onModuleInit();
2522
expect(pool.size).toBe(1);
@@ -32,7 +29,7 @@ describe('MediasoupWorkerPool', () => {
3229
});
3330

3431
it('getNextWorker는 round-robin으로 순환한다', async () => {
35-
const pool = new MediasoupWorkerPool(baseOptions(2), noopLogger);
32+
const pool = new MediasoupWorkerPool(baseOptions(2), noopLogger());
3633
try {
3734
await pool.onModuleInit();
3835
const w1 = pool.getNextWorker();
@@ -46,7 +43,7 @@ describe('MediasoupWorkerPool', () => {
4643
});
4744

4845
it('onModuleDestroy 후엔 모든 worker가 closed 상태가 된다', async () => {
49-
const pool = new MediasoupWorkerPool(baseOptions(1), noopLogger);
46+
const pool = new MediasoupWorkerPool(baseOptions(1), noopLogger());
5047
await pool.onModuleInit();
5148
const worker = pool.getNextWorker();
5249
await pool.onModuleDestroy();

‎apps/backend/src/meeting/application/meeting-idle.scheduler.spec.ts‎

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
import { IdleSweepOutcome, MeetingService } from '@/meeting/application/meeting.service';
2-
import { PinoLoggerAdapter } from '@/shared-kernel/infrastructure/pino-logger.adapter';
2+
import { noopLogger } from '@/shared-kernel/testing/noop-logger';
33
import { stub } from '@/shared-kernel/testing/stub';
44

55
import { MeetingIdleScheduler } from './meeting-idle.scheduler';
66

7-
function silentLogger(): PinoLoggerAdapter {
8-
return stub<PinoLoggerAdapter>({ debug: jest.fn(), info: jest.fn(), warn: jest.fn(), error: jest.fn() });
9-
}
10-
117
const NOTHING_CLOSED: IdleSweepOutcome = { scanned: 0, closed: 0 };
128

139
describe('MeetingIdleScheduler.sweep', () => {
@@ -16,7 +12,7 @@ describe('MeetingIdleScheduler.sweep', () => {
1612
sweepIdleMeetings: jest.fn(async () => NOTHING_CLOSED),
1713
});
1814

19-
await new MeetingIdleScheduler(service, silentLogger()).sweep();
15+
await new MeetingIdleScheduler(service, noopLogger()).sweep();
2016

2117
expect(service.sweepIdleMeetings).toHaveBeenCalledTimes(1);
2218
});
@@ -34,7 +30,7 @@ describe('MeetingIdleScheduler.sweep', () => {
3430
return NOTHING_CLOSED;
3531
},
3632
});
37-
const scheduler = new MeetingIdleScheduler(service, silentLogger());
33+
const scheduler = new MeetingIdleScheduler(service, noopLogger());
3834

3935
const first = scheduler.sweep();
4036
await scheduler.sweep();
@@ -52,7 +48,7 @@ describe('MeetingIdleScheduler.sweep', () => {
5248
throw new Error('redis down');
5349
},
5450
});
55-
const scheduler = new MeetingIdleScheduler(service, silentLogger());
51+
const scheduler = new MeetingIdleScheduler(service, noopLogger());
5652

5753
await expect(scheduler.sweep()).resolves.toBeUndefined();
5854
await scheduler.sweep();

‎apps/backend/src/meeting/application/meeting-recovery.service.spec.ts‎

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ import { MeetingCode } from '@/meeting/domain/value-objects/meeting-code';
77
import { ChatEntry } from '@/shared-kernel/domain/value-objects/chat-entry';
88
import { externalReference } from '@/shared-kernel/domain/value-objects/external-reference';
99
import { NestEventBusDomainEventPublisher } from '@/shared-kernel/infrastructure/nest-event-bus.publisher';
10-
import { PinoLoggerAdapter } from '@/shared-kernel/infrastructure/pino-logger.adapter';
11-
import { stub } from '@/shared-kernel/testing/stub';
10+
import { noopLogger } from '@/shared-kernel/testing/noop-logger';
1211

1312
import { MeetingService } from './meeting.service';
1413
import { MeetingRecoveryService } from './meeting-recovery.service';
@@ -18,13 +17,6 @@ interface CapturedEvent {
1817
payload: unknown;
1918
}
2019

21-
const noopLogger = (): PinoLoggerAdapter => stub<PinoLoggerAdapter>({
22-
debug: jest.fn(),
23-
info: jest.fn(),
24-
warn: jest.fn(),
25-
error: jest.fn(),
26-
});
27-
2820
const CRASHED_AT = new Date('2026-01-01T00:00:00Z');
2921
const BOOTED_AT = new Date('2026-01-01T00:05:00Z');
3022

‎apps/backend/src/meeting/application/meeting.service.spec.ts‎

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ import { MeetingCode } from '@/meeting/domain/value-objects/meeting-code';
1111
import { ChatEntry, chatEntry } from '@/shared-kernel/domain/value-objects/chat-entry';
1212
import { externalReference, NO_EXTERNAL_REFERENCE } from '@/shared-kernel/domain/value-objects/external-reference';
1313
import { NestEventBusDomainEventPublisher } from '@/shared-kernel/infrastructure/nest-event-bus.publisher';
14-
import { PinoLoggerAdapter } from '@/shared-kernel/infrastructure/pino-logger.adapter';
15-
import { stub } from '@/shared-kernel/testing/stub';
14+
import { noopLogger } from '@/shared-kernel/testing/noop-logger';
1615

1716
import {
1817
MeetingClosedError,
@@ -39,13 +38,6 @@ const makeEventPublisher = () => {
3938
};
4039
};
4140

42-
const noopLogger = (): PinoLoggerAdapter => stub<PinoLoggerAdapter>({
43-
debug: jest.fn(),
44-
info: jest.fn(),
45-
warn: jest.fn(),
46-
error: jest.fn(),
47-
});
48-
4941
const code = MeetingCode.from('abc12xyz');
5042

5143
const makeMeeting = (startedAt: Date) =>

‎apps/backend/src/notion/application/notion-meeting-provisioning.service.spec.ts‎

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,14 @@
11
import { CreatedMeeting, CreateMeetingInput, MeetingService } from '@/meeting/application/meeting.service';
22
import { NotionMeetingProvisioningService } from '@/notion/application/notion-meeting-provisioning.service';
33
import { NotionIssuePort, PendingIssue } from '@/notion/domain/ports/notion-issue.port';
4-
import { PinoLoggerAdapter } from '@/shared-kernel/infrastructure/pino-logger.adapter';
5-
import { stub } from '@/shared-kernel/testing/stub';
4+
import { noopLogger } from '@/shared-kernel/testing/noop-logger';
65

76
/**
87
* private 필드를 가진 구체 서비스의 테스트 대역.
98
* 인터페이스가 아니라 클래스를 주입받으므로, 이 테스트가 실제로 쓰는 메서드만 구현해 넘긴다.
109
*/
1110
const stubService = <T,>(impl: Partial<T>): T => impl as T;
1211

13-
function silentLogger(): PinoLoggerAdapter {
14-
return stub<PinoLoggerAdapter>({ debug: jest.fn(), info: jest.fn(), warn: jest.fn(), error: jest.fn() });
15-
}
16-
1712
function fakeMeetingCreation(code: string): {
1813
port: MeetingService;
1914
inputs: CreateMeetingInput[];
@@ -63,7 +58,7 @@ describe('NotionMeetingProvisioningService 회의 카드', () => {
6358
fakeMeetingCreation('ABC123').port,
6459
notionIssue,
6560
'https://convene.example.com',
66-
silentLogger(),
61+
noopLogger(),
6762
);
6863

6964
it('이슈 페이지에 회의 링크와 같은 주소로 카드를 심는다', async () => {
@@ -98,7 +93,7 @@ describe('NotionMeetingProvisioningService.provisionForIssue', () => {
9893
meetingCreation.port,
9994
notionIssue.port,
10095
'https://convene.example.com',
101-
silentLogger(),
96+
noopLogger(),
10297
);
10398

10499
const result = await service.provisionForIssue('issue-1', '스프린트 회고');
@@ -127,7 +122,7 @@ describe('NotionMeetingProvisioningService.provisionForIssue', () => {
127122
fakeMeetingCreation('ABC').port,
128123
throwingLinkWriter(),
129124
'https://x',
130-
silentLogger(),
125+
noopLogger(),
131126
);
132127

133128
await expect(service.provisionForIssue('issue-1', null)).rejects.toThrow();
@@ -138,7 +133,7 @@ describe('NotionMeetingProvisioningService.provisionForIssue', () => {
138133
fakeMeetingCreation('ABC').port,
139134
throwingLinkWriter(),
140135
'https://x',
141-
silentLogger(),
136+
noopLogger(),
142137
);
143138

144139
const result = await service.provisionForIssue('issue-1', null, { bestEffortLink: true });
@@ -158,7 +153,7 @@ describe('NotionMeetingProvisioningService.pollPendingIssues', () => {
158153
meetingCreation.port,
159154
notionIssue.port,
160155
'https://x',
161-
silentLogger(),
156+
noopLogger(),
162157
);
163158

164159
const outcome = await service.pollPendingIssues(new Date());
@@ -184,7 +179,7 @@ describe('NotionMeetingProvisioningService.pollPendingIssues', () => {
184179
meetingCreation,
185180
notionIssue.port,
186181
'https://x',
187-
silentLogger(),
182+
noopLogger(),
188183
);
189184

190185
const outcome = await service.pollPendingIssues(new Date());

‎apps/backend/src/notion/application/notion-polling.scheduler.spec.ts‎

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,10 @@ import {
33
PollOutcome,
44
} from '@/notion/application/notion-meeting-provisioning.service';
55
import { NotionPollingScheduler } from '@/notion/application/notion-polling.scheduler';
6-
import { PinoLoggerAdapter } from '@/shared-kernel/infrastructure/pino-logger.adapter';
76
import { SystemClock } from '@/shared-kernel/infrastructure/system.clock';
7+
import { noopLogger } from '@/shared-kernel/testing/noop-logger';
88
import { stub } from '@/shared-kernel/testing/stub';
99

10-
function silentLogger(): PinoLoggerAdapter {
11-
return stub<PinoLoggerAdapter>({ debug: jest.fn(), info: jest.fn(), warn: jest.fn(), error: jest.fn() });
12-
}
13-
1410
function fixedClock(now: Date): SystemClock {
1511
return { now: () => now };
1612
}
@@ -28,7 +24,7 @@ describe('NotionPollingScheduler.poll', () => {
2824
},
2925
});
3026

31-
await new NotionPollingScheduler(provisioning, fixedClock(now), silentLogger()).poll();
27+
await new NotionPollingScheduler(provisioning, fixedClock(now), noopLogger()).poll();
3228

3329
expect(times).toEqual([now]);
3430
});
@@ -46,7 +42,7 @@ describe('NotionPollingScheduler.poll', () => {
4642
return NOTHING_FOUND;
4743
},
4844
});
49-
const scheduler = new NotionPollingScheduler(provisioning, fixedClock(new Date()), silentLogger());
45+
const scheduler = new NotionPollingScheduler(provisioning, fixedClock(new Date()), noopLogger());
5046

5147
const first = scheduler.poll();
5248
await scheduler.poll();
@@ -64,7 +60,7 @@ describe('NotionPollingScheduler.poll', () => {
6460
throw new Error('notion down');
6561
},
6662
});
67-
const scheduler = new NotionPollingScheduler(provisioning, fixedClock(new Date()), silentLogger());
63+
const scheduler = new NotionPollingScheduler(provisioning, fixedClock(new Date()), noopLogger());
6864

6965
await expect(scheduler.poll()).resolves.toBeUndefined();
7066
await scheduler.poll();

‎apps/backend/src/notion/application/notion-report-push.service.spec.ts‎

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { NotionReportPort } from '@/notion/domain/ports/notion-report.port';
44
import { FinalizedReport, ReportLookupService } from '@/reports/application/report-lookup.service';
55
import { reportSummary } from '@/shared-kernel/domain/value-objects/report-summary';
66
import { NestEventBusDomainEventPublisher } from '@/shared-kernel/infrastructure/nest-event-bus.publisher';
7-
import { PinoLoggerAdapter } from '@/shared-kernel/infrastructure/pino-logger.adapter';
7+
import { noopLogger } from '@/shared-kernel/testing/noop-logger';
88
import { stub } from '@/shared-kernel/testing/stub';
99

1010
import { NotionReportPushService } from './notion-report-push.service';
@@ -27,10 +27,6 @@ const finalizedReport = (issueId: string | null): FinalizedReport => ({
2727
}),
2828
});
2929

30-
function silentLogger(): PinoLoggerAdapter {
31-
return stub<PinoLoggerAdapter>({ debug: jest.fn(), info: jest.fn(), warn: jest.fn(), error: jest.fn() });
32-
}
33-
3430
const makeService = (options: {
3531
found?: FinalizedReport | null;
3632
lookupError?: Error;
@@ -60,7 +56,7 @@ const makeService = (options: {
6056
notionReport,
6157
{ now: () => pushedAt },
6258
eventPublisher,
63-
silentLogger(),
59+
noopLogger(),
6460
);
6561
return { service, pushed, events, reportLookup, notionReport };
6662
};

0 commit comments

Comments
 (0)