Skip to content

Commit 1173a62

Browse files
refactor: 统一 log.ts/debug.ts 的测试 mock 为共享定义
- 新增 tests/mocks/log.ts 和 tests/mocks/debug.ts,覆盖源文件全部实际导出 - 移除旧 mock 中不存在的导出(logToFile、logEvent、getLogFilePath) - 13 个测试文件改为使用共享 mock,避免定义分散和不一致 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 7ea69ca commit 1173a62

16 files changed

Lines changed: 87 additions & 134 deletions

File tree

CLAUDE.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,18 @@ Feature flags control which functionality is enabled at runtime. 代码中统一
263263

264264
被迫 mock 的根源:`log.ts` / `debug.ts``bootstrap/state.ts`(模块级 `realpathSync` / `randomUUID` 副作用)。必须 mock 的模块:`log.ts``debug.ts``bun:bundle``settings/settings.js``config.ts``auth.ts`、第三方网络库。
265265

266+
**`log.ts``debug.ts` 使用共享 mock**`tests/mocks/log.ts` / `tests/mocks/debug.ts`),不要在测试文件中内联 mock 定义。使用方式:
267+
268+
```ts
269+
import { logMock } from "../../../tests/mocks/log";
270+
mock.module("src/utils/log.ts", logMock);
271+
272+
import { debugMock } from "../../../../tests/mocks/debug";
273+
mock.module("src/utils/debug.ts", debugMock);
274+
```
275+
276+
源文件导出变更时只需更新 `tests/mocks/` 下的对应文件,不需要逐个修改测试。
277+
266278
不要 mock:纯函数模块(`errors.ts``stringUtils.js`)、mock 值与真实实现相同的模块、mock 路径与实际 import 不匹配的模块。
267279

268280
路径规则:统一用 `.ts` 扩展名 + `src/*` 别名路径,禁止双重 mock 同一模块。

packages/builtin-tools/src/tools/AgentTool/__tests__/agentToolUtils.test.ts

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { mock, describe, expect, test } from "bun:test";
2+
import { debugMock } from "../../../../../../tests/mocks/debug";
23

34
// ─── Mocks for agentToolUtils.ts dependencies ───
45
// Only mock modules that are truly unavailable or cause side effects.
@@ -87,20 +88,7 @@ mock.module("src/tasks/LocalAgentTask/LocalAgentTask.js", () => ({
8788
updateProgressFromMessage: noop,
8889
}));
8990

90-
mock.module("src/utils/debug.ts", () => ({
91-
getMinDebugLogLevel: () => "warn",
92-
isDebugMode: () => false,
93-
enableDebugLogging: () => false,
94-
getDebugFilter: () => null,
95-
isDebugToStdErr: () => false,
96-
getDebugFilePath: () => null,
97-
setHasFormattedOutput: noop,
98-
getHasFormattedOutput: () => false,
99-
flushDebugLogs: async () => {},
100-
logForDebugging: noop,
101-
getDebugLogPath: () => "",
102-
logAntError: noop,
103-
}));
91+
mock.module("src/utils/debug.ts", debugMock);
10492

10593
mock.module("src/utils/errors.js", () => ({
10694
ClaudeError: class extends Error {},

packages/builtin-tools/src/tools/CtxInspectTool/__tests__/CtxInspectTool.test.ts

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,7 @@
11
import { afterEach, beforeEach, describe, expect, mock, test } from 'bun:test'
2+
import { logMock } from '../../../../../../tests/mocks/log'
23

3-
mock.module('src/utils/log.ts', () => ({
4-
logError: () => {},
5-
logToFile: () => {},
6-
getLogDisplayTitle: () => '',
7-
logEvent: () => {},
8-
logMCPError: () => {},
9-
logMCPDebug: () => {},
10-
dateToFilename: (d: Date) => d.toISOString().replace(/[:.]/g, '-'),
11-
getLogFilePath: () => '/tmp/mock-log',
12-
attachErrorLogSink: () => {},
13-
getInMemoryErrors: () => [],
14-
loadErrorLogs: async () => [],
15-
getErrorLogByIndex: async () => null,
16-
captureAPIRequest: () => {},
17-
_resetErrorLogForTesting: () => {},
18-
}))
4+
mock.module('src/utils/log.ts', logMock)
195

206
mock.module('src/services/tokenEstimation.ts', () => ({
217
roughTokenCountEstimation: (text: string) => Math.ceil(text.length / 4),

packages/builtin-tools/src/tools/FileEditTool/__tests__/utils.test.ts

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,8 @@
11
import { mock, describe, expect, test } from "bun:test";
2+
import { logMock } from "../../../../../../tests/mocks/log";
23

34
// Mock log.ts to cut the heavy dependency chain
4-
mock.module("src/utils/log.ts", () => ({
5-
logError: () => {},
6-
logToFile: () => {},
7-
getLogDisplayTitle: () => "",
8-
logEvent: () => {},
9-
logMCPError: () => {},
10-
logMCPDebug: () => {},
11-
dateToFilename: (d: Date) => d.toISOString().replace(/[:.]/g, "-"),
12-
getLogFilePath: () => "/tmp/mock-log",
13-
attachErrorLogSink: () => {},
14-
getInMemoryErrors: () => [],
15-
loadErrorLogs: async () => [],
16-
getErrorLogByIndex: async () => null,
17-
captureAPIRequest: () => {},
18-
_resetErrorLogForTesting: () => {},
19-
}));
5+
mock.module("src/utils/log.ts", logMock);
206

217
const {
228
normalizeQuotes,

packages/builtin-tools/src/tools/LSPTool/__tests__/formatters.test.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import { mock, describe, expect, test } from "bun:test";
2+
import { debugMock } from "../../../../../../tests/mocks/debug";
23

3-
mock.module("src/utils/debug.ts", () => ({
4-
logForDebugging: () => {},
5-
isDebugMode: () => false,
6-
}));
4+
mock.module("src/utils/debug.ts", debugMock);
75

86
const {
97
formatGoToDefinitionResult,

src/services/langfuse/__tests__/langfuse.test.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { mock, describe, test, expect, beforeEach } from 'bun:test'
2+
import { debugMock } from '../../../../tests/mocks/debug'
23

34
// Mock @langfuse/otel before any imports
45
const mockForceFlush = mock(() => Promise.resolve())
@@ -71,9 +72,7 @@ mock.module('@langfuse/tracing', () => ({
7172
}))
7273

7374
// Mock debug logger
74-
mock.module('src/utils/debug.ts', () => ({
75-
logForDebugging: mock(() => {}),
76-
}))
75+
mock.module('src/utils/debug.ts', debugMock)
7776

7877
// Mock user data — resolveLangfuseUserId uses getCoreUserData().email and .deviceId
7978
mock.module('src/utils/user.js', () => ({

src/services/mcp/__tests__/officialRegistry.test.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import { mock, describe, expect, test, afterEach } from "bun:test";
2+
import { debugMock } from "../../../../tests/mocks/debug";
23

34
mock.module("axios", () => ({
45
default: { get: async () => ({ data: { servers: [] } }) },
56
}));
6-
mock.module("src/utils/debug.ts", () => ({
7-
logForDebugging: () => {},
8-
}));
7+
mock.module("src/utils/debug.ts", debugMock);
98

109
const { isOfficialMcpUrl, resetOfficialMcpUrlsForTesting } = await import(
1110
"../officialRegistry"

src/utils/__tests__/envValidation.test.ts

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,8 @@
11
import { mock, describe, expect, test } from "bun:test";
2+
import { debugMock } from "../../../tests/mocks/debug";
23

34
// Mock debug.ts to cut bootstrap/state dependency chain
4-
mock.module("src/utils/debug.ts", () => ({
5-
logForDebugging: () => {},
6-
isDebugMode: () => false,
7-
isDebugToStdErr: () => false,
8-
getDebugFilePath: () => null,
9-
getDebugFilter: () => null,
10-
getMinDebugLogLevel: () => "debug",
11-
getDebugLogPath: () => "/tmp/mock-debug.log",
12-
flushDebugLogs: async () => {},
13-
enableDebugLogging: () => false,
14-
setHasFormattedOutput: () => {},
15-
getHasFormattedOutput: () => false,
16-
logAntError: () => {},
17-
}));
5+
mock.module("src/utils/debug.ts", debugMock);
186

197
const { validateBoundedIntEnvVar } = await import("../envValidation");
208

src/utils/__tests__/json.test.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
import { mock, describe, expect, test } from "bun:test";
2+
import { logMock } from "../../../tests/mocks/log";
23

34
// Mock log.ts to cut the heavy dependency chain (log.ts → bootstrap/state.ts → analytics)
4-
mock.module("src/utils/log.ts", () => ({
5-
logError: () => {},
6-
logToFile: () => {},
7-
getLogDisplayTitle: () => "",
8-
logEvent: () => {},
9-
}));
5+
mock.module("src/utils/log.ts", logMock);
106

117
const { safeParseJSON, safeParseJSONC, parseJSONL, addItemToJSONCArray } =
128
await import("../json");

src/utils/__tests__/memoize.test.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
import { mock, describe, expect, test, beforeEach } from "bun:test";
2+
import { logMock } from "../../../tests/mocks/log";
23

34
// Mock log.ts to cut the bootstrap/state dependency chain
4-
mock.module("src/utils/log.ts", () => ({
5-
logError: () => {},
6-
logToFile: () => {},
7-
getLogDisplayTitle: () => "",
8-
logEvent: () => {},
9-
}));
5+
mock.module("src/utils/log.ts", logMock);
106

117
const { memoizeWithTTL, memoizeWithTTLAsync, memoizeWithLRU } = await import(
128
"../memoize"

0 commit comments

Comments
 (0)