162

I'm new to TDD and xUnit so I want to test my method that looks something like:

List<T> DeleteElements<T>(this List<T> a, List<T> b);

Is there any Assert method that I can use ? I think something like this would be nice

List<int> values = new List<int>() { 1, 2, 3 };
List<int> expected = new List<int>() { 1 };
List<int> actual = values.DeleteElements(new List<int>() { 2, 3 });

Assert.Exact(expected, actual);

Is there something like this ?

martijnn2008
  • 3,552
  • 5
  • 30
  • 40
Petar Petrov
  • 2,729
  • 2
  • 22
  • 17

6 Answers6

203

2021-Apr-01 update

I recommend using FluentAssertions. It has a vast IntelliSense-friendly assertion library for many use cases including collections

collection.Should().Equal(1, 2, 5, 8);
collection.Should().NotEqual(8, 2, 3, 5);
collection.Should().BeEquivalentTo(8, 2, 1, 5);

Original answer

xUnit.Net recognizes collections so you just need to do

Assert.Equal(expected, actual); // Order is important

You can see other available collection assertions in CollectionAsserts.cs

For NUnit library collection comparison methods are

CollectionAssert.AreEqual(IEnumerable, IEnumerable) // For sequences, order matters

and

CollectionAssert.AreEquivalent(IEnumerable, IEnumerable) // For sets, order doesn't matter

More details here: CollectionAssert

MbUnit also has collection assertions similar to NUnit: Assert.Collections.cs

Konstantin Spirin
  • 20,609
  • 15
  • 72
  • 90
44

In the current version of XUnit (1.5) you can just use

Assert.Equal(expected, actual);

The above method will do an element by element comparison of the two lists. I'm not sure if this works for any prior version.

hwiechers
  • 14,583
  • 8
  • 53
  • 62
  • 21
    The problem I encountered with Assert.Equal for collections is that it fails if the collections' elements are in different orders, even if the elements are present in both. – Scott Lawrence Apr 18 '12 at 20:06
  • 1
    @ScottA.Lawrence Lists have order too! Do you get the same behavior with HashSets? – johv Jul 18 '12 at 09:13
  • @johv I haven't tested it with HashSets, but that's a good idea. Once I've had a chance to try it I'll try to remember to answer here. – Scott Lawrence Jul 18 '12 at 16:06
  • HashSets are still compared in order – bdukes Mar 25 '14 at 22:21
  • 2
    It also seems to fail if the collection types are different, even if they both contain the same items in the same order. – James White Mar 03 '15 at 03:00
  • @James White It's cause of default Equals comparator. You must override default Equals() and GetHashCode() – aligin Jan 17 '18 at 14:04
  • 7
    But it has a very crappy output. It does not tell you WHERE two lists differ! :( – Zordid Sep 25 '18 at 15:05
  • @ScottLawrence LINQ is a good friend here, e.g. expected.OrderBy(x => x.something) and then the same on sut exec result collection. – Max Sep 20 '19 at 21:02
  • @Zordid An alternative might be to `Zip` the two together, and then iterate over every pair, calling `Assert.Equal` on each. – Zev Spitz Jan 23 '22 at 11:11
  • @Zordid There's a fixed issue filed [here](https://github.com/xunit/xunit/issues/994) and it's been fixed since 2.4.2-pre.9 – Zev Spitz Jan 23 '22 at 11:18
24

With xUnit, should you want to cherry pick properties of each element to test you can use Assert.Collection.

Assert.Collection(elements, 
  elem1 => Assert.Equal(expect1, elem1.SomeProperty),
  elem2 => { 
     Assert.Equal(expect2, elem2.SomeProperty);
     Assert.True(elem2.TrueProperty);
  });

This tests the expected count and ensures that each action is verified.

Drew Williams
  • 598
  • 4
  • 13
5

Recently, I was using xUnit 2.4.0 and Moq 4.10.1 packages in my asp.net core 2.2 app.

In my case I managed to get it work with two steps process:

  1. Defining an implementation of IEqualityComparer<T>

  2. Pass the comparer instance as a third parameter into Assert.True method:

    Assert.True(expected, actual, new MyEqualityComparer());

But there is another nicer way to get the same result using FluentAssertions package. It allows you to do the following:

// Assert          
expected.Should().BeEquivalentTo(actual));

Interestingly that Assert.Equal() always fails even when I ordered the elements of two lists to get them in the same order.

Community
  • 1
  • 1
Dmitry Stepanov
  • 2,776
  • 8
  • 29
  • 45
  • 3
    something is wrong with your ordering BeEquivalentTo doesnt care about order (thats why your test passes with BeEquivalentTo and not with assert.Equal) – RagnaRock May 17 '19 at 10:44
2

In the current version of xUnit v2.4.2 you can also use:

Assert.Equivalent(expected: ..., actual: ..., strict: true);

The strict parameter influences this comparison by requiring that all values in the expected list are in the actual list (meaning expected: [1, 2] is equivalent to actual: [2, 3, 1] when strict is false, but not equivalent when strict is true).

Yauheni Pakala
  • 868
  • 9
  • 16
1

Just found the NotStrictEqual that seems to do it.

Toby Kolk
  • 56
  • 5
  • 4
    NotStrictEqual might pass, but it will also pass when given two arrays with no common elements at all. It's not a useful assertion for this problem. – Chris Dueck Nov 18 '21 at 10:06