Skip to content

Collection expectations

Davyd McColl edited this page Oct 14, 2017 · 2 revisions

You can assert equality of collections:

Expect(strings).To.Be.Equal.To(new[] { "one", "two", "three" });

And equivalence (meaning that all items must be present and collection sizes must still match, but order is irrelevant):

Expect(strings).To.Be.Equivalent.To(new[] { "three", "one", "two" });

The obvious syntax for containment is:

Expect(strings).To.Contain("moo");

Whilst this is available, I've often found this to be lacking - a collection of strings with one "moo" or three "moo" values both pass the test. So we have:

Expect(strings).To.Contain.Exactly(1).Equal.To("moo");

Similarly, we can test with upper and lower boounds:

Expect(strings).To.Contain.At.Least(1).Equal.To("moo");
Expect(strings).To.Contain.At.Most(1).Equal.To("moo");

And there are convenience synonyms: Any(), None(). You could test these in other ways:

Expect(strings).Not.To.Contain.Any().Equal.To("cow");
Expect(strings).To.Contain.None().Equal.To("cow");
Expect(strings).To.Contain.Exactly(0).Equal.To("cow");

Remember, NExpect is not here to be opinionated, but rather to facilitate readable tests.

We can also test that the collection has nothing else but our sought value:

Expect(strings).To.Contain.Only(1).Equal.To("moo");

Sometimes we just want to pre-check that we have a certain number of items, without caring about their values. You could:

Expect(strings.Count()).To.Equal(1);

But I prefer:

Expect(strings).To.Contain.Exactly(1).Item();
Expect(ints).To.Contain.Exactly(3).Items();

You can use .At.Least, .At.Most and .Only here (although, when testing for .Items(), .Only and .Exactly end up meaning pretty-much the same thing).

You can also take advantage of Deep and Intersection equality testing:

Expect(persons).To.Contain.Exactly(1).Deep.Equal.To(new { 
  Id = 42, 
  Name = "Douglas Adams", 
  DateOfBirth = new DateTime(1952, 3, 11) 
});
Expect(persons).To.Contain.Exactly(1).Intersection.Equal.To(new {
  Name = "Terry Pratchett",
  DateOfBirth = new DateTime(1948, 4, 28)
});

Or use a Func to match with:

Expect(persons).To.Contain.Exactly(1).Matched.By(p => p.Name == "Douglas Adams");

Or you can implement an IEqualityComparer and pass that in as a parameter to .Equal.To.