refactor(test+ci): 放弃 Testcontainers 改用 docker-compose#8
Testcontainers 1.19.7 → 1.20.6 → 1.21.3 三次升级,CI 的 CAP_NET_RAW 反序列化问题都没修。深入分析后得出:这不是版本问题,是架构问题——Testcontainers 依赖 docker-java 跟进 Docker daemon 协议,只要 daemon 继续演进而 docker-java 没跟上,问题就会反复以不同形态出现。
切换为显式 docker-compose:
Testcontainers (@Testcontainers + @Container) ↓ 去掉 docker-compose.test.yml(PG 15 + Redis 7) ↓ CI 脚本 docker compose up -d @SpringBootTest 通过 application-test.yml 连 localhost:5432/6379
功能测试历史上第一次在本地/CI 真正跑起来,立刻暴露了两个隐藏 bug(之前完全被 Testcontainers 跑不起来的事实所遮蔽):
InventoryServiceImpl.deduct: @Retryable(retryFor = OptimisticLockingFailureException.class) → 抛 BusinessException → spring-retry 包装为 ExhaustedRetryException(Cannot locate recovery method) → GlobalExceptionHandler 兜底为 500 + code=50000
修复:新增 ExhaustedRetryException 处理器,解包 cause 后委派;@Retryable 显式 noRetryFor = {BusinessException, NotFoundException}。
ExhaustedRetryException
@Retryable
noRetryFor = {BusinessException, NotFoundException}
GlobalExceptionHandler.mapStatus 只把 INVALID_PARAM (40001) 单独映射到 422;其他 40002~40099 错误码全部走默认 BAD_REQUEST(400)。违反 project-architecture §5.3 错误码规范。
GlobalExceptionHandler.mapStatus
INVALID_PARAM (40001)
BAD_REQUEST(400)
project-architecture §5.3
修复:区间判定 40001~40099 → 422。
refactor(test)
fix(exception)
test(order)
chore(ci)
docs(framework)
OpenApiExportTest
target/openapi.json
Req1OrderCreateTest
不可执行的测试比没有测试更糟。此次切换让埋藏的 2 个 bug 浮出水面,证明:有假的测试保障,比没有测试还危险——你会误以为有了功能测试的门禁而放松警惕,暗处的 bug 不断累积。
FB-02 正式 RESOLVED。剩余未完成清单已清零——所有功能测试、单元测试、契约校验、真实编译硬门禁都通过。
决策链
Testcontainers 1.19.7 → 1.20.6 → 1.21.3 三次升级,CI 的 CAP_NET_RAW 反序列化问题都没修。深入分析后得出:这不是版本问题,是架构问题——Testcontainers 依赖 docker-java 跟进 Docker daemon 协议,只要 daemon 继续演进而 docker-java 没跟上,问题就会反复以不同形态出现。
切换为显式 docker-compose:
意外发现的 2 个真实业务 Bug
功能测试历史上第一次在本地/CI 真正跑起来,立刻暴露了两个隐藏 bug(之前完全被 Testcontainers 跑不起来的事实所遮蔽):
Bug A — @Retryable 吞业务异常
修复:新增
ExhaustedRetryException处理器,解包 cause 后委派;@Retryable显式noRetryFor = {BusinessException, NotFoundException}。Bug B — 错误码区间映射不全
GlobalExceptionHandler.mapStatus只把INVALID_PARAM (40001)单独映射到 422;其他 40002~40099 错误码全部走默认BAD_REQUEST(400)。违反project-architecture §5.3错误码规范。修复:区间判定 40001~40099 → 422。
5 个 commit
refactor(test)fix(exception)test(order)chore(ci)docs(framework)验证(历史第一次全绿)
OpenApiExportTest:契约文件target/openapi.json20KB 产出Req1OrderCreateTest8 个 AC 全部通过(ac1~ac8 + 补充用例)沉淀到框架的元级原则
不可执行的测试比没有测试更糟。此次切换让埋藏的 2 个 bug 浮出水面,证明:有假的测试保障,比没有测试还危险——你会误以为有了功能测试的门禁而放松警惕,暗处的 bug 不断累积。
后续
FB-02 正式 RESOLVED。剩余未完成清单已清零——所有功能测试、单元测试、契约校验、真实编译硬门禁都通过。