6

in a test I need to test an object:

IEnumerable<int> Ids.

The collection contains the numbers 1,2 and 3.

I basically wanted to test that there are three ids in Ids and that 1,2 and 3 are all present.

The problem is there isn't a count on IEnumerable.

I thought I was going to be able to go:

Assert.AreEqual(3, Ids.Count);

Anyone know how to do this and how to ensure 1,2 and 3 are the actual numbers in there?

Kirill Polishchuk
  • 54,804
  • 11
  • 122
  • 125
AnonyMouse
  • 18,108
  • 26
  • 79
  • 131

4 Answers4

9
Assert.IsTrue(Ids.SequenceEqual(Enumerable.Range(1, 3));

Tests not only that there are three numbers, but that there are the numbers 1, 2 and 3 in that order by making sure each element matches the corresponding element from Enumerable.Range(1, 3).

Edit: Combining the Range from here with with Kirill Polishchuk's answer, would suggest:

CollectionAssert.AreEqual(Enumerable.Range(1, 3), Ids);

If your Ids doesn't give an ordering, the simplest test for correctness is to apply that ordering in the test, bringing us back to being able to apply the above:

CollectionAssert.AreEqual(Enumerable.Range(1, 3), Ids.OrderBy(x => x));
Jon Hanna
  • 110,372
  • 10
  • 146
  • 251
  • For anyone else who stumbled open this via google (like I did), `CollectionAssert` requires `ICollection` as input, so you either need to cast it (if you know the object actually implements `ICollection`) or call `ToList()` on the `IEnumerable`s. – Setsu Sep 11 '21 at 20:19
6

You can use LINQ extension methods for these needs:

using System.Linq;

…

Assert.AreEqual(3, Ids.Count());

Assert.IsTrue(Ids.Contains(1));
//etc.

If you want to have exactly the same items in exactly the same order, there is also:

Assert.IsTrue(Ids.SequenceEqual(new List<int>{ 1, 2, 3 }));

Ordering is not guaranteed according to the semantics of IEnumerable<T>, but that may not be of consequence in your particular scenario.

Jay
  • 56,361
  • 10
  • 99
  • 123
  • What do you mean by "ordering is not guaranteed"? While `IEnumerable` makes no promise beyond "0 or more T", if a given implementation has an order, it'll be maintained. It's as much guaranteed in a given case as e.g. the given case guaranteeing 3 items. – Jon Hanna Aug 30 '12 at 09:13
  • Oh wait. Of course, there's nothing in what the OP said that entails `Ids` having an order. Sorry, I get you now. – Jon Hanna Aug 30 '12 at 09:15
6

Take a look at CollectionAssert class, it verifies true/false propositions associated with collections in unit tests.

Kirill Polishchuk
  • 54,804
  • 11
  • 122
  • 125
3

FluentAssertions are fantastic, providing a set of extension methods that aid testing:

Here is an excerpt from their docs

IEnumerable collection = new[] { 1, 2, 5, 8 };

collection.Should().NotBeEmpty()
     .And.HaveCount(4)
     .And.ContainInOrder(new[] { 2, 5 })
     .And.ContainItemsAssignableTo<int>();

collection.Should().Equal(new list<int> { 1, 2, 5, 8 });
collection.Should().Equal(1, 2, 5, 8);
collection.Should().BeEquivalent(8, 2, 1, 5);
collection.Should().NotBeEquivalent(8, 2, 3, 5);

collection.Should().HaveCount(c => c > 3).And.OnlyHaveUniqueItems();
collection.Should().HaveSameCount(new[] {6, 2, 0, 5});

collection.Should().BeSubsetOf(new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, });
collection.Should().Contain(8).And.HaveElementAt(2, 5).And.NotBeSubsetOf(new[] {11, 56});
collection.Should().Contain(x => x > 3); 
collection.Should().Contain(collection, 5, 6); // It should contain the original items, plus 5 and 6.
collection.Should().OnlyContain(x => x < 10);
collection.Should().OnlyContainItemsOfType<int>();
collection.Should().NotContain(82);
collection.Should().NotContainNulls();
collection.Should().NotContain(x => x > 10);

collection = new int[0];
collection.Should().BeEmpty();
trh178
  • 11,228
  • 5
  • 28
  • 37
Mr. Mr.
  • 4,257
  • 3
  • 27
  • 42