From 20b11b96aae00174b0f33a58af5a4c29e30bc249 Mon Sep 17 00:00:00 2001 From: Simon Cropp Date: Sat, 29 Aug 2026 17:12:31 +1000 Subject: [PATCH] Run before callbacks from the file level InnerVerifier constructor Dispose calls RunAfterCallbacks unconditionally, and the primary constructor calls RunBeforeCallbacks, but the constructor used by third party clients to verify a file directly never did. So an OnVerify(before, after) pair registered against those settings, or globally, had only its after half executed. Anything the pair sets and restores, such as a culture, ambient state or a counter, was left unbalanced. --- .../InnerVerifyTests/InnerVerifyTests.cs | 19 +++++++++++++++++++ src/Verify/Verifier/InnerVerifier.cs | 6 ++++++ 2 files changed, 25 insertions(+) diff --git a/src/Verify.Tests/InnerVerifyTests/InnerVerifyTests.cs b/src/Verify.Tests/InnerVerifyTests/InnerVerifyTests.cs index e2608e251..d1c3627b5 100644 --- a/src/Verify.Tests/InnerVerifyTests/InnerVerifyTests.cs +++ b/src/Verify.Tests/InnerVerifyTests/InnerVerifyTests.cs @@ -24,6 +24,25 @@ public async Task VerifyExternalFile() #endregion + // Dispose runs the after callbacks, so this constructor has to run the before half + // too. An unbalanced pair leaves whatever it pushes, sets or counts in the wrong state. + [Fact] + public void RunsBeforeAndAfterCallbacks() + { + var calls = new List(); + var settings = new VerifySettings(); + settings.OnVerify( + before: () => calls.Add("before"), + after: () => calls.Add("after")); + + using (new InnerVerifier(targetDirectory, "callbackBalance", settings)) + { + Assert.Equal(["before"], calls); + } + + Assert.Equal(["before", "after"], calls); + } + [Fact] public async Task VerifyExternalFileLocked() { diff --git a/src/Verify/Verifier/InnerVerifier.cs b/src/Verify/Verifier/InnerVerifier.cs index 5f4aec22d..898d83476 100644 --- a/src/Verify/Verifier/InnerVerifier.cs +++ b/src/Verify/Verifier/InnerVerifier.cs @@ -196,6 +196,12 @@ public InnerVerifier(string directory, string name, VerifySettings? settings = n this.settings = settings; } + // Dispose runs the after callbacks unconditionally, so the before callbacks have + // to run here too. Otherwise an OnVerify(before, after) pair registered by a + // consumer of this API has its after half executed unbalanced, leaving whatever + // the pair pushes, sets or counts in the wrong state. + this.settings.RunBeforeCallbacks(); + SetVerifyHasBeenRun(name); this.directory = directory;