0

I'm using FluentAssertions and I need to compare 2 lists of objects. They are from the same class which contains the Values property.

I want to compare both lists but I want all Values from list1 to exist on list2, but ignore extra values. Something like this:

using System.Collections.Generic;
using FluentAssertions;

public class Program
{

    public class Value
    {
        public int Id { get; set; }
        public string SomeValue { get; set; }
    }

    public class MyClass
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public List<Value> Values { get; set; }
    }


    public static void Main()
    {
        var list1 = new List<MyClass>
        {
            new MyClass
            {
                Id = 1,
                Name = "Name 1",
                Values = new List<Value>
                {
                    new Value {Id = 1, SomeValue = "Test" }
                }
            }
        };

        var list2 = new List<MyClass>
        {
            new MyClass
            {
                Id = 1,
                Name = "Name 1",
                Values = new List<Value>
                {
                    new Value {Id = 1, SomeValue = "Test" },
                    new Value {Id = 2, SomeValue = "Test" }
                }
            }
        };

        list2.Should().HaveSameCount(list1);

        // This doesn't throw, just proving that the first object is equivalent
        list2[0].Values[0].ShouldBeEquivalentTo(list1[0].Values[0]);
        for (var x = 0; x < list2.Count; x++)
        {
            list2[x].ShouldBeEquivalentTo(list1[x], options => options.Excluding(s => s.Values));
            // This throws, but it shouldn't
            list2[x].Values.Should().Contain(list1[x].Values);
        }

    }
}

But this throws:

Expected collection {

Program+Value { Id = 1 SomeValue = "Test" },

Program+Value { Id = 2 SomeValue = "Test" }} to contain

Program+Value { Id = 1 SomeValue = "Test" }

So a few questions:

  1. Why isn't Contains working as expected?

  2. Is it possible to do that in one line, for example changing the default list comparison to use Contains instead of ShouldBeEquivalentTo?

  3. How do I exclude a property from a collection of a class? I have looked at this question and this one but they don't seem to apply to collections. Also, the program doesn't compile if I try using PropertyPath. I'm using .Net Core, but I also tried with 4.6 and it doesn't woek either.

Community
  • 1
  • 1
Ricardo Smania
  • 2,939
  • 2
  • 26
  • 35

2 Answers2

1

I can answer your first question so the problem is that the objects new Value {Id = 1, SomeValue = "Test" } in list1 and list2 are two completely separate and different objects, no matter that the properties are equal. If you modify it to this it will work as you expect

    var commonValue = new Value { Id = 1, SomeValue = "Test" };

    var list1 = new List<MyClass>
    {
        new MyClass
        {
            Id = 1,
            Name = "Name 1",
            Values = new List<Value>
            {
                commonValue
            }
        }
    };

    var list2 = new List<MyClass>
    {
        new MyClass
        {
            Id = 1,
            Name = "Name 1",
            Values = new List<Value>
            {
                commonValue,
                new Value {Id = 2, SomeValue = "Test" }
            }
        }
    };
  • Yes, but I want to compare for equivalency, and in that case it shouldn't throw the exception, as shown on this line: list2[0].Values[0].ShouldBeEquivalentTo(list1[0].Values[0]); – Ricardo Smania Sep 09 '16 at 11:53
0

Just use ShouldBeEquivalentTo. It will compare two object graphs for structural equivalence.

Dennis Doomen
  • 8,368
  • 1
  • 32
  • 44