Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 431
knittl Avatar asked Apr 01 '14 06:04

knittl


2 Answers

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.

like image 87
Erik Philips Avatar answered Nov 19 '22 14:11

Erik Philips


I think it's personal preference really but for I go for:

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

Using linq and if the underlying collection/Enumerable type changed it would still work in most cases, you not testing the type just the count. This also works for things that don't have .Count on them like IDBSet for example. But then again I don't see anything wrong with .AreEqual either. If the next engineer understands then it's a winner, eh?

like image 25
jolySoft Avatar answered Nov 19 '22 15:11

jolySoft