Verify 必须在 MSTest/xUnit/NUnit 的测试方法中 await 调用,依赖测试上下文和生命周期,否则抛出“No test context found”异常;默认仅序列化 public 属性,快照文件需提交至 Git,.received 文件应被忽略。

Verify 不是“配置完就能跑”的快照库,它依赖测试框架的生命周期和输出路径约定;不显式调用 Verify 方法、不处理 .received 文件、不启用差异工具,就等于没真正用起来。
Verify 必须配合 MSTest/xUnit/NUnit 的 TestMethod 才能工作
Verify 本身不运行测试,它只是在测试执行过程中介入断言环节。如果你把它当成普通工具类直接调用(比如在控制台 Main 里写 await Verify(myObj)),会抛出 InvalidOperationException: No test context found。
- 必须在标记了
[TestMethod](MSTest)、[Fact](xUnit)或[Test](NUnit)的方法体内调用Verify - Verify 会自动读取当前测试方法的全名(如
PrimeServiceTests.IsPrime_ReturnsTrueFor7)生成快照文件名,路径默认为__snapshots__/IsPrime_ReturnsTrueFor7.verified.txt - 首次运行时,Verify 只生成
.verified.*,不会失败;后续运行若内容不一致,则生成.received.*并让测试失败
Verify 需要显式 await,且返回值不能丢弃
Verify 的核心方法(如 Verify(object)、Verify(string))全部返回 Task,不是同步 void 方法。忽略 await 或用 void 声明测试方法,会导致测试提前结束、快照未写入、结果不可靠。
- 错误写法:
Verify(myModel); // 编译通过但快照不生效 - 正确写法:
await Verify(myModel); - MSTest 中必须把测试方法声明为
public async Task MyTest(),不能是void - xUnit 同理,
[Fact]方法必须返回Task
Verify 默认只序列化 public 属性,private/field 不进快照
Verify 使用 System.Text.Json(.NET 6+)或 Newtonsoft.Json(旧版)做序列化,默认行为是只导出 public getter 属性。如果你的对象有 [JsonIgnore]、[XmlIgnore] 或自定义 converter,快照会静默跳过这些成员——但你可能根本没意识到。
- 验证方式:打开生成的
.verified.json,确认字段是否齐全;若缺,检查属性访问修饰符和序列化特性 - 想包含 private 字段?需手动注册自定义
JsonSerializerOptions,传给VerifySettings,再传入Verify调用 - 枚举默认输出名称(
"Active"),不是数值;如需数值,得配JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase, false))
快照文件不进 Git 就失去意义,但 .received 文件必须被忽略
Verify 的可靠性建立在「已提交的 .verified.* 是权威基准」之上。如果团队成员各自本地生成快照却不提交,或者误把 .received.* 提交了,整个机制就崩了。
- 必须把
__snapshots__/目录加入 Git(不要加**/__snapshots__/**/.received.*) - 推荐在项目根目录的
.gitignore里加一行:**/__snapshots__/**/*.received.* - CI 环境(如 GitHub Actions)跑 Verify 测试前,务必确保
__snapshots__/已拉取最新 —— 否则会因找不到.verified.*直接报错
最常被跳过的其实是 dotnet verify CLI 工具的初始化:不运行 dotnet tool install -g Verify.Tools,就没法用命令行一键接受变更;不配 IDE 插件(Rider/ReSharper),就只能靠改文件名来“更新快照”,极易出错。快照测试的威力不在写法多炫,而在整个链路是否闭环 —— 从生成、比对、差异查看到合入基准,缺一不可。


















