Skip to content

IsEquivalentToAssertionExtensions.IsEquivalentTo should work with Native AOT when using a custom comparer #3851

@sliekens

Description

@sliekens

Hi,

I hope I understand correctly but it appears that IsEquivalentTo is annotated with RequiresUnreferencedCode because of the use of a reflection-based comparer (StructuralEqualityComparer<TItem>.Instance).

However, there is an overload where you can provide your own comparer, but that one also has RequiresUnreferencedCode, and I don't think that is necessarily correct as you would typically pass in a bespoke comparer without reflection.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net10.0</TargetFramework>
    <PublishAot>true</PublishAot>
    <OutputType>Exe</OutputType>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="TUnit" Version="1.1.10" />
  </ItemGroup>
</Project>
public class CollectionTest
{
    [Test]
    public async Task Test()
    {
        List<int> list1 = [1, 2, 3];
        List<int> list2 = [2, 3, 1];

        // error IL2026: Using member 'TUnit.Assertions.Extensions.IsEquivalentToAssertionExtensions.IsEquivalentTo<TCollection, TItem>(IAssertionSource<TCollection>, IEnumerable<TItem>, IEqualityComparer<TItem>, CollectionOrdering, String, String, String)'
        // which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code.
        // Collection equivalency uses structural comparison for complex objects, which requires reflection and is not compatible with AOT.
        await Assert.That(list1).IsEquivalentTo(list2, comparer: EqualityComparer<int>.Default);
    }
}

The IsEquivalentToAssertion type may need to be split up into a reflection-based version and a version for custom comparers.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions