Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the idiomatic way to verify collection size in xUnit?

I have in my test suite a test that goes something like this:

[Fact] public void VerifySomeStuff() {     var stuffCollection = GetSomeStuff();      Assert.Equal(1, stuffCollection.Count()); } 

This test works as I expect, but when I run it xUnit prints a warning:

warning xUnit2013: Do not use Assert.Equal() to check for collection size.

However, no alternative is suggested in the warning, and a google search takes me to the source code in xUnit for the test that verifies this warning is printed.

If Assert.Equal() isn't the correct way to verify the length of a collection, what is?


To clarify: I realize that I could "trick" xUnit into not emitting this warning by e.g. extracting a variable or using Assert.True(stuff.Count() == 1) instead. The latter is just hacky, and the former feels like if xUnit is e.g. trying to avoid multiple iterations of an IEnumerable<T>, then this is the wrong way to go (because I'll get compiler hints about that separately if it's an issue), and xUnit itself should never have to evaluate the input more than once (in fact it probably will get the same input regardless of variable extraction, because of how C# function calling works).

So, I'm not just interested in removing that warning from my output. An answer to my question also explains why that warning is included in the library in the first place and why whatever approach I should use instead is better.

like image 526
Tomas Aschan Avatar asked Oct 09 '17 19:10

Tomas Aschan


2 Answers

Xunit offers quick fixes for most of its warnings, so you should be able to see what it thinks is "right".

xunit

In your case, it wants you to use Assert.Single since you are expecting exactly one item. If you were asserting an arbitrary number, like 412, then it would not give you a warning about using Count. It will only suggest using Single if you are expecting one item, or Empty if you are expecting no items.

like image 129
vcsjones Avatar answered Sep 21 '22 09:09

vcsjones


The rule only applies when testing for 0 or 1 items in collection.

Assert.Equal(0, result.Length) // rule warning, use .Empty Assert.Equal(1, result.Length) // rule warning, use .Single Assert.Equal(2, result.Length) // ok 

To satisy rule:

Assert.Empty(result); // for 0 items Assert.Single(result); // for 1 item Assert.NotEmpty(result); // for 1 or more items 

When using Assert.NotEmpty we may as well be precise with a count

Assert.Equal(2, result.Length) // Does not violate rule xUnit2013 

https://xunit.net/xunit.analyzers/rules/xUnit2013

like image 29
Tikall Avatar answered Sep 22 '22 09:09

Tikall