tpierrain/NFluent

Reflection 'Parameter count mismatch' when comparing lists

Closed this issue · 3 comments

The following test program fails, and the test failure reports System.Reflection.TargetParameterCountException: 'Parameter count mismatch.'

I'm not 100% sure of the best way to compare lists in NFluent, but I'm pretty sure it shouldn't be failing with that exception.

Thank you!

public class NTest
    {
        private class TestCase
        {
            public List<int> Items { get; set; } = new List<int>();
        }

        [Fact]
        public void Test()
        {
            TestCase a = new TestCase();
            TestCase b = new TestCase();

            a.Items.Add(1);
            a.Items.Add(2);
            a.Items.Add(3);

            b.Items.Add(1);
            b.Items.Add(2);
            b.Items.Add(3);

            Check.That(a).Considering().Public.Properties.IsEqualTo(b);
        }
    }

Thanks for taking the time to report this.
I look into this right now.

I confirm I reproduce this issue with the latest version.

Overview

The fix has been implemented, but it will not provide the result you probably expect, as it implies ignoring the content of the Items property.
To get the result you are looking for, you should probably override the Equals method of the class you want to check (TestCase here).
Also, to check for enumeration, you can use ContentsExactly(...), such as:

Check.That(a.Items).ContainsExactly(b.Items);

Note also that your sample works if you use arrays:

       public class NTest
        {
            private class TestCase
            {
                public int[] Items { get; set; }
            }

            [Fact]
            public void Test()
            {
                TestCase a = new TestCase();
                TestCase b = new TestCase();

                a.Items = new []{1, 2, 3};
                b.Items = new []{1, 2, 3};

                Check.That(a).Considering().Public.Properties.IsEqualTo(b);
            }
        }

Detailed explaination

To be more specific, the fix disregards the array of int's that is wrapped by the List class. It is because it is expressed as an indexed property. This leads to a crash with the current versions as NFluent try to get the content without providing an index value.
The Net reflection APIs provide no information regarding the legal values for the index; therefore the fixed version simply ignore the property, as it cannot guess the index value to be used.

Why fixing this is complex

Assuming I find a proper way to handle indexed properties, this check will still be fragile.
for exemple, the following check fails:

           [Fact]
            public void Test()
            {
                TestCase a = new TestCase();
                TestCase b = new TestCase();

                a.Items.Add(1);
                a.Items.Add(2);
                a.Items.Add(3);
                // deliberately add extra items and remove them
                a.Items.Add(4);
                a.Items.Add(5);
                a.Items.Remove(4);
                a.Items.Remove(3);

                b.Items.Add(1);
                b.Items.Add(2);
                b.Items.Add(3);

                Check.That(a).Considering().Public.Properties.IsEqualTo(b);
            }

With an error on the Capacity property:

The checked value's property 'Items.Capacity' does not have the expected value.
The checked value's property 'Items.Capacity':
	[8]
The expected value's property 'Items.Capacity':
	[4]

because adding extra entries led the List class to allocate a larger array. It may be or not be the desired behaviour depending on what you are testing for.

I will create another issue to request a general solution for this problem.