# 内购测试里最容易被误读的一种红:断言的是「全新实例应处于未解锁状态」,挂掉的原因却不是断言本身… > 内购测试里最容易被误读的一种红:断言的是「全新实例应处于未解锁状态」,挂掉的原因却不是断言本身,而是测试会话在清理商店状态时被服务层拒绝——错误域落在 SKServiceError - Canonical page: https://obelisk.club/blog/build-log-1846 - Author: Peter Zhang - Published: 2026-10-11 - Tags: build-log 内购测试里最容易被误读的一种红:断言的是「全新实例应处于未解锁状态」,挂掉的原因却不是断言本身,而是测试会话在清理商店状态时被服务层拒绝——错误域落在 SKServiceErrorDomain(底下包着 SKInternalErrorDomain),日志里能看到「Error deleting all transactions」的记录。 这种失败为什么长期隐形:在测试报告里,它就是满屏绿中的一格红,和真正的产品断言失败长得一模一样;而它依赖模拟器里持久化的商店状态,重跑常常就绿了,于是被当作 flake 重试掉。但「代码没变、结果变了」恰恰是诊断结论:测试读到的不是你写的逻辑,而是上一轮运行残留的交易。断言「全新实例未解锁」只在重置成功时才有意义;重置失败还继续跑断言,等于在脏状态上验证一条干净状态的承诺。 修复的顺序是承重的: 1. 先归因再动手。服务层的错误码出现在重置步骤,是环境判决,不是产品判决——先别去改权益逻辑。 2. 把前置条件显式化。setUp 里的商店重置若失败,应以独立的、写明「测试商店未能重置」的方式失败,而不是让断言替它背锅;报告里分不清机器与断言,后来的人就会去修错的东西。 3. 隔离状态。每个测试自己持有会话、自己重置;并行的多个测试目标不要共享同一台模拟器的商店状态。 4. 守护进程卡死时,擦掉模拟器状态再跑,而不是原地重跑——脏状态活在模拟器里,不在代码里,重跑只会继承它。 5. 断言本身不动摇。「全新安装未解锁」是收入路径的地基:修环境,不修断言。 一分钟自检:在同一台模拟器上背靠背跑两遍内购套件——第二遍在第一遍绿的地方红了,就说明「全新状态」继承自残留交易,重置路径是装饰性的;再看看重置抛出的错误在哪里被接住,若被吞进断言的路径里,你永远分不清是机器坏了还是产品坏了。