nunit/nunit.analyzers

NUnit2022 should allow Count on enumerables

zeppelin37 opened this issue · 4 comments

The Analyzer NUnit2022 complains that IEnumerable does not have a Count property. Which is technically true. But the test itself works.

[Test]
public void Test()
{
    var enumerable = new [] {1,2,3}.Where(i => i > 1);

    // Actual argument type 'IEnumerable<int>' has no property 'Count'.
    Assert.That(enumerable, Has.Count.EqualTo(2));
}

If NUnit supports the Has.Count constraint on an enumerable and the test is actually green, there is nothing wrong with the test. Why should I change it? Why does the Analyzer complain?

@zeppelin37 Can you provide some more information? E.g. the version of NUnit and other packages, and perhaps a full minimal example?

If I run the test above (under dotnet 8 with NUnit v. 4.1.0, NUnit3TestAdapter v. 4.5.0, and NUnit.Analyzers v. 4.1.0), then the test fails with

  Failed Test [22 ms]
  Error Message:
   System.ArgumentException : Property Count was not found on System.Linq.Enumerable+WhereArrayIterator`1[System.Int32]. (Parameter '_name')
  Stack Trace:
     at NUnit.Framework.Constraints.PropertyConstraint.ApplyTo[TActual](TActual actual)
   at NUnit.Framework.Assert.That[TActual](TActual actual, IResolveConstraint expression, NUnitString message, String actualExpression, String constraintExpression)

Maybe the code path was not taken at all? nunit/nunit#158 suggests that Has.Count has not been supported for IEnumerable<T>s in the past 10 years, so it seems safe to close the issue.

I found out that the affected test actually returns a List, but as static type IEnumerable, so my example in the ticket description is wrong. It is more like this:

IEnumerable<string> GetEnumerable() 
{
    return new List<int> { 1, 2, 3 };
}
Assert.That(GetEnumerable(), Has.Count.EqualTo(3));

I understand that analyzers cannot know what happens at runtime, so I guess I have to change the return type, or suppress the warning.

The analyzer works on declared types at compile time, not real types at runtime.