Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Oct 27, 2025

Custom ArgumentDisplayFormatter attributes were ignored because the display name was computed and cached before discovery event receivers ran, where formatters are registered.

public class Foo
{
    public override string ToString() => throw new Exception("Should not be called");
}

[Test]
[MethodDataSource(nameof(Data))]
[ArgumentDisplayFormatter<FooFormatter>]  // Was being ignored
public void Test(Foo foo) { }

Changes

  • TUnit.Core/TestContext.cs: Added InvalidateDisplayNameCache() to clear cached display name
  • TUnit.Engine/Building/TestBuilder.cs: Invalidate cache after discovery event receivers complete in BuildTestAsync()
  • TUnit.TestProject/ArgumentDisplayFormatterTests.cs: Added test coverage for formatters with MethodDataSource, Arguments, and exception-throwing ToString()

Flow

Before: GetDisplayName() → cache result → discovery events → formatters registered (too late)

After: GetDisplayName() → cache result → discovery events → formatters registered → invalidate cache → next GetDisplayName() uses formatters

Original prompt

This section details on the original issue you should resolve

<issue_title>ArgumentDisplayFormatter is being ignored in 0.77.3</issue_title>
<issue_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.1s

I found that this happens because the argument display value is computed before the formatter is added.

The argument display value is being created here:

// 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:

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.</issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] Fix ArgumentDisplayFormatter handling in tests Fix ArgumentDisplayFormatter ignored due to premature display name caching Oct 27, 2025
Copilot finished work on behalf of thomhurst October 27, 2025 20:53
Copilot AI requested a review from thomhurst October 27, 2025 20:53
@thomhurst thomhurst marked this pull request as ready for review October 27, 2025 20:55
@thomhurst thomhurst enabled auto-merge (squash) October 27, 2025 20:55
@thomhurst thomhurst merged commit 125bdfb into main Oct 27, 2025
19 of 21 checks passed
@thomhurst thomhurst deleted the copilot/fix-argument-display-formatter branch October 27, 2025 21:18
@claude claude bot mentioned this pull request Oct 27, 2025
1 task
This was referenced Nov 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ArgumentDisplayFormatter is being ignored in 0.77.3

2 participants