-
-
Notifications
You must be signed in to change notification settings - Fork 96
Description
A custom ArgumentDisplayFormatter is being ignored. Here's a minimal reproduction with a failing test because of it (here's a repo with the repro):
public class Tests
{
[Test]
[MethodDataSource(nameof(Data1))]
[ArgumentDisplayFormatter<FooFormatter>]
public void Test1(Foo foo)
{
}
public IEnumerable<Foo> Data1() => [new()];
}
public class Foo
{
public override string ToString() => throw new Exception("Foo.ToString");
}
public class FooFormatter : ArgumentDisplayFormatter
{
public override bool CanHandle(object? value) => true;
public override string FormatValue(object? value) => "FooFormatterValue";
}The test fails because the FooFormatter isn't being used and the Foo.ToString() method gets called and throws:
PS D:\Projects\others\TUnitBugs> dotnet test
Restore complete (0.4s)
TUnitBugs succeeded (0.2s) → TUnitBugs\bin\Debug\net9.0\TUnitBugs.dll
TUnitBugs test failed with 2 error(s) (0.4s)
D:\\Projects\\others\\TUnitBugs\\TUnitBugs\\Tests.cs(3): error test failed:
Test1 (0ms): InvalidOperationException: Failed to expand data source for test 'Test1': Foo.ToString
D:\Projects\others\TUnitBugs\TUnitBugs\bin\Debug\net9.0\TUnitBugs.dll : error run failed: Tests failed: 'D:\Projects\others\TUnitBugs\TUnitBugs\bin\Debug\net9.0\TestResults\TUnitBugs_net9.0_x64.log' [net9.0|x64]
Test summary: total: 1, failed: 1, succeeded: 0, skipped: 0, duration: 0.3s
Build failed with 2 error(s) in 1.1sI found that this happens because the argument display value is computed before the formatter is added.
The argument display value is being created here:
TUnit/TUnit.Engine/Building/TestBuilder.cs
Lines 771 to 783 in 6ed6416
| // Create the test object BEFORE invoking event receivers | |
| // This ensures context.InternalExecutableTest is set for error handling in registration | |
| var creationContext = new ExecutableTestCreationContext | |
| { | |
| TestId = testId, | |
| DisplayName = context.GetDisplayName(), | |
| Arguments = testData.MethodData, | |
| ClassArguments = testData.ClassData, | |
| Context = context, | |
| TestClassInstanceFactory = testData.TestClassInstanceFactory, | |
| ResolvedMethodGenericArguments = testData.ResolvedMethodGenericArguments, | |
| ResolvedClassGenericArguments = testData.ResolvedClassGenericArguments | |
| }; |
Which happens before the events are executed for the test later:
TUnit/TUnit.Engine/Building/TestBuilder.cs
Line 803 in 6ed6416
| await InvokeDiscoveryEventReceiversAsync(context); |
And ArgumentDisplayFormatterAttribute depends on having it's OnTestDiscovered executed so it could add the argument formatter.
I discovered this, because I have a class that throws for the default argument formatter, so I'm using a custom one to make sure my tests don't fail. Except right now the tests are failing anyways.