# 1. 不可变对象(immutable object)的可测试性中天然线程安全、hash 稳定 A 不可变对象仍有可变状态,需要加锁方能线程安全 B 不可变对象天然线程安全、hash 稳定,测试无需考虑状态迁移与并发副作用,确定性高 ✓ 正确答案 C 不可变对象作为 HashMap 的 key 会因为内容变化而失效 D 不可变对象无法被测试,因为没有 setter
# 2. 依赖注入(DI)的可测试性中测试时替换实现 A DI 让类自己 new 依赖,测试无法替换 B DI 只与 Spring 容器相关,与可测试性无关 C DI 通过构造器/接口注入依赖,使被测类只依赖抽象,测试时可替换为 fake/stub/mock 实现隔离 ✓ 正确答案 D 依赖注入后测试必须连接真实数据库
# 3. 函数式编程(FP)的可测试性中组合性、引用透明性 A 纯函数依赖外部状态,测试需要大量 setup B FP 函数无法组合,测试只能逐个写死 C 引用透明性使输出只由输入决定、测试确定性强,组合性让子函数独立可测、测试可复用 ✓ 正确答案 D FP 增加共享可变状态,降低可测试性
# 4. 可验证设计(verifiable design)中架构层面的可测试性设计(Hexagonal、Clean、Onion) A 这些架构让领域逻辑依赖数据库和框架,可测试性差 B 可验证设计只与测试工具相关,与架构无关 C 通过依赖倒置与端口抽象让领域逻辑不依赖外部技术,可脱离基础设施独立、快速测试 ✓ 正确答案 D 这些架构增加了测试的复杂度,不利于单元测试
# 5. 纯函数(pure function)的可测试性中无副作用、无全局状态 A 纯函数依赖全局状态,测试需要先设置环境 B 纯函数无法做 I/O,因此无法被测试 C 纯函数无副作用、无全局状态,相同输入必得相同输出,测试确定、简单、可并行 ✓ 正确答案 D 纯函数测试必须 mock 外部依赖
# 6. 面向接口的设计(interface-oriented design)中 mock vs stub 的实现替换 A 接口是替换点,测试可注入 stub 提供数据或 mock 验证交互,选择取决于要验证结果还是交互 ✓ 正确答案 B 面向接口设计让代码依赖具体类,测试无法替换 C mock 和 stub 功能完全相同,没有区别 D 面向接口设计只适用于大型框架,与单元测试无关
# 7. 领域逻辑与技术细节的分离(Hexagonal)中 domain 不依赖 infrastructure A domain 直接依赖数据库和框架,无法独立测试 B domain 只依赖端口接口、不依赖 infrastructure,可脱离数据库/框架独立测试,适配器单独验证 ✓ 正确答案 C 六边形架构让领域逻辑与基础设施耦合,降低可测试性 D domain 依赖 infrastructure 是正常设计,不影响测试
# 8. Mock 过度使用的反模式中测试与实现细节耦合、重构时大面积失效,如何用真实依赖与契约测试替代? A 对内部协作对象大量 mock 并断言内部调用,会让测试与实现细节耦合、重构时大面积失效 ✓ 正确答案 B Mock 越多测试越可靠,应尽可能对所有依赖都 mock C 过度 mock 不会影响测试稳定性,因为 mock 是确定性的 D 契约测试与 mock 完全等价,无区别
# 9. 生产验证的"A/B 测试"(A/B test)中统计显著性的实验 A A/B 测试只需对比两组结果,无需考虑样本量和随机波动 B p 值越小说明样本量越大,与效果无关 C 通过随机分组与统计显著性(p 值、样本量、置信区间)判断差异是否由真实效果引起,避免随机波动误判 ✓ 正确答案 D A/B 测试与金丝雀发布完全相同,都只验证稳定性
# 10. 可测试的 ID 生成(testable ID)中 IDGenerator 接口 A 直接在业务里调用 UUID.randomUUID() 最容易测试,因为值是唯一的 B 测试用真实雪花 ID 才能断言具体值 C ID 生成无法测试,因为每次值都不同 D 通过 IDGenerator 接口抽象并注入可控实现,可确定性断言生成的 ID,也便于换生成策略 ✓ 正确答案
# 11. 可测试的时间(testable time)中 Clock 接口、@ClockProvider A 直接调用 System.currentTimeMillis() 最容易测试,因为时间是真实的 B 测试必须等待真实时间流逝才能验证过期 C 时间逻辑无法测试,因为时间总是变化的 D 通过注入 Clock 接口,测试用固定/可控时钟,可精确确定地测试超时、过期等时间逻辑 ✓ 正确答案
# 12. 可测试的数据库(testable DB)中 Repository 接口、Testcontainers A 测试应共享一个全局数据库,以便复用数据 B 所有数据库测试都应使用内存数据库,因为它与生产完全一致 C Testcontainers 只能用于单元测试,无法验证真实 SQL D 领域逻辑测试用 Repository 接口+内存实现,真实 SQL 验证用 Testcontainers 启动真实数据库容器 ✓ 正确答案
# 13. 可测试的网络(testable network)中 HttpClient 接口 A 通过 HttpClient 接口抽象,用 stub/mock/测试服务器(MockWebServer/WireMock)覆盖成功、错误、超时、重试等场景 ✓ 正确答案 B 直接用真实 HttpClient 测试最可靠,因为网络是真实的 C 网络调用无法测试,因为依赖外部服务 D 测试网络必须连接真实的外部服务
# 14. 可测试的并发与异步(testable async)中如何抽象线程池、调度器与超时策略,以便在测试中控制并发时序? A 通过抽象线程池/调度器/超时策略,测试注入同步执行器、可控调度器与固定时钟,把时序变成可控变量 ✓ 正确答案 B 并发逻辑无法测试,因为线程调度不可控 C 测试并发应在代码里用固定 sleep 猜测时序 D 异步测试必须用真实线程池并按真实时序运行
# 15. 可测试的外部副作用(testable side effects)中邮件、短信、支付回调等外部副作用如何通过端口抽象隔离并在测试中替换? A 外部副作用无法测试,因为必须调用真实外部服务 B 副作用触发与否不是业务逻辑,无需测试 C 测试副作用应直接调用真实邮件服务,才能保证真实 D 通过端口抽象隔离副作用,测试注入记录型替身验证"是否触发、参数是否正确",真实发送由适配器负责 ✓ 正确答案
# 16. 可测试的配置与特性开关中配置源抽象与 feature flag 注入如何使测试覆盖多配置组合? A 直接读取 System.getProperty 和全局静态常量,测试最容易控制 B 通过配置源与 feature flag 抽象注入,测试用内存配置覆盖多配置组合与开关状态 ✓ 正确答案 C 配置只在运行时生效,测试无法影响 D feature flag 只能用于生产,无法在测试中控制
# 17. 行为验证 vs 状态验证的取舍中何时用 spy/mock 验证交互,何时应断言结果状态? A 所有测试都应使用行为验证,因为能验证实现细节 B 优先用状态验证断言可观察结果,仅当需要验证与外部边界的交互契约时才用 spy/mock 行为验证 ✓ 正确答案 C 状态验证与行为验证完全相同,可互换 D 行为验证永远比状态验证更可靠
# 18. 可测试的随机(testable random)中 Random 接口、seed 可控 A 随机逻辑无法测试,因为每次结果都不同 B 通过 Random 接口抽象与固定 seed,测试可注入可控随机源或复现序列,确定性断言随机决策逻辑 ✓ 正确答案 C 测试随机应直接调用 Math.random(),这样才能保证真实 D seed 可控不影响测试,因为随机无法预测
# 19. 不可测试代码的信号中 new、静态方法、Singleton 与全局状态如何阻碍测试,重构优先级如何排? A new、静态方法、Singleton、全局状态都能让测试轻松替换依赖 B 全局状态不影响测试,因为测试可以共享 C 无状态纯函数静态工具类(如 StringUtils)最阻碍测试,应最先重构 D new 硬编码依赖、静态方法、Singleton、全局状态阻碍依赖替换与状态隔离;重构优先解决 new 硬编码(构造器注入),再治理静态/单例与全局状态 ✓ 正确答案