Skip to content

Commit 86d0832

Browse files
committed
Guard TUnit parameter binding and null TestContext
Two fixes in the same method, sharing one helper. TestMethodArguments holds the raw pre-binding arguments: TUnit bundles a params array at invocation time. SetParameters was called with them unconditionally, so a [Arguments(1, 2, 3)] test with a params int[] parameter ran fine under TUnit but threw 'The number of passed in parameters (3) must not exceed the number of parameters for the method (1)' from every Verify call. The argument count is now compared with the parameter name count first, matching MSTest and XunitV3. TestContext.Current is nullable, and is null in a [Before(TestSession)] hook or any code that does not flow the test context. Both BuildVerifier and VerifyChecks.Run dereferenced it with !, giving a bare NullReferenceException. They now throw the same kind of explanatory error the other adapters do.
1 parent d731cfb commit 86d0832

4 files changed

Lines changed: 38 additions & 5 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
6
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
public class ParamsArrayTests
2+
{
3+
// TestMethodArguments holds the raw pre-binding arguments, which TUnit bundles into
4+
// the params array at invocation time. So the argument count does not match the
5+
// parameter count and the arguments cannot be used for snapshot naming.
6+
[Test]
7+
[Arguments(1, 2, 3)]
8+
public Task ParamsArray(params int[] values) =>
9+
Verify(values.Sum());
10+
}

src/Verify.TUnit/Verifier.cs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,20 @@ static Task AddFile(string path)
2020
public static void AddAttachmentEvents() =>
2121
VerifierSettings.AddTestAttachment(AddFile);
2222

23+
// TestContext.Current is null outside a test, for example in a
24+
// [Before(TestSession)] hook or in code that does not flow the test context.
25+
// Dereferencing it there gives a bare NullReferenceException.
26+
internal static TestDetails CurrentTestDetails()
27+
{
28+
var context = TestContext.Current;
29+
if (context is null)
30+
{
31+
throw new("TestContext.Current is null. Verify can only be used from within a test method.");
32+
}
33+
34+
return context.Metadata.TestDetails;
35+
}
36+
2337
public static InnerVerifier BuildVerifier(string sourceFile, VerifySettings settings, bool useUniqueDirectory = false, int lineNumber = 0)
2438
{
2539
Guards.AgainstBadSourceFile(sourceFile);
@@ -28,16 +42,24 @@ public static InnerVerifier BuildVerifier(string sourceFile, VerifySettings sett
2842
settings.UseUniqueDirectory();
2943
}
3044

31-
var details = TestContext.Current!.Metadata.TestDetails;
45+
var details = CurrentTestDetails();
3246
var type = details.MethodMetadata.Class.Type;
3347
var classArguments = details.TestClassArguments;
3448
var methodArguments = details.TestMethodArguments;
49+
var parameterNames = details.GetParameterNames();
3550
if (!settings.HasParameters &&
3651
(classArguments.Length > 0 ||
3752
methodArguments.Length > 0))
3853
{
39-
settings.SetParameters([.. classArguments, .. methodArguments]);
40-
settings.SetClassArgumentCount(classArguments.Length);
54+
// Only apply when the argument count matches the parameter count. A params
55+
// array exposes raw pre-binding arguments, which TUnit bundles at invocation
56+
// time, so the counts differ and parameterized snapshot naming would throw.
57+
// MSTest and XunitV3 apply the same guard.
58+
if (classArguments.Length + methodArguments.Length == parameterNames?.Count)
59+
{
60+
settings.SetParameters([.. classArguments, .. methodArguments]);
61+
settings.SetClassArgumentCount(classArguments.Length);
62+
}
4163
}
4264

4365
VerifierSettings.AssignTargetAssembly(type.Assembly);
@@ -49,7 +71,7 @@ public static InnerVerifier BuildVerifier(string sourceFile, VerifySettings sett
4971
settings,
5072
type.NameWithParent(),
5173
method.Name,
52-
details.GetParameterNames(),
74+
parameterNames,
5375
pathInfo,
5476
lineNumber);
5577
}

src/Verify.TUnit/VerifyChecks.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ public static class VerifyChecks
55
{
66
public static Task Run()
77
{
8-
var details = TestContext.Current!.Metadata.TestDetails;
8+
var details = Verifier.CurrentTestDetails();
99
var type = details.MethodMetadata.Class.Type;
1010
VerifierSettings.AssignTargetAssembly(type.Assembly);
1111
return InnerVerifyChecks.Run(type.Assembly);

0 commit comments

Comments
 (0)