Search code examples
.netunit-testingcollectionsnunitassert

Most idiomatic way in NUnit to assert equal length on collections


What's the most idiomatic way with NUnit 2.6 to assert that two collections are of equal length regardless of their elements' values?

I can see several ways of expressing that assertion. Which one is preferred, or are there disadvantages/advantages with using one or the other?

Assert.That(coll1, Has.Count.EqualTo(coll2.Count));
Assert.That(coll1.Count, Is.EqualTo(coll2.Count));
Assert.AreEqual(coll1.Count, coll2.Count);

I can see that the first option provides a nice output in case the assertion failed (Expected count of ... but actually got ...), whereas the other two options only output "Expected ..., actual ..." unless I provide a custom message through an additional parameter.


Solution

  • I prefer:

    Assert.That(collection, Has.Count.EqualTo(expectedCount));
    

    Simply because .Count and Count() could be incorrectly overridden (which should be tested in a different unit test if they are, although I don't know how nunit is actually doing the count internally). Bascially I don't want my actual to have any side affect logic. Calling Count or Count() should probably be done in the act like:

    // Arrange
    var expectedCount = 8;
    
    // Act
    var list = GetList();
    var actualCount = list.Count();
    
    // Assert
    Assert.That(actualCount, Is.EqualTo(expectedCount));
    

    Both read fairly the same, but the first one has less logic to look over when it fails.

    Update: dec-1-2020

    Considering the number of upvotes this has received, I think I should mention that using https://fluentassertions.com/ (FA) is advantageous. This could be written in the following ways and reads much nicer:

    // Arrange
    
    // Act
    var list = GetList();
    
    // Assert
    list.Should().BeEmpty();
    

    or

    // Arrange
    
    // Act
    var list = GetList();
    
    // Assert
    list.Should().HaveCount(8);
    

    or

    // Arrange
    
    // Act
    var list = GetList();
    
    // Assert
    list.Should().HaveCountLessThanOrEqualTo(10);
    

    Beyond the OP question, FA can do some very advanced collection rules:

    // Arrange
    
    // Act
    var persons = GetPersons();
    
    // Assert
    persons.Should().BeInAscendingOrder(p => p.LastName)
      .And().OnlyHaveUniqueItems(p => p.id);
    

    The framework goes way beyond collections and adds readability to testing other topics as well.

    // Arrange
    
    // Act
    Action action = () => 8 / 0;
    
    //
    action.Should().Throw<DivideByZeroException>();
    

    I have no association with fluent assertions.