FluentAssertion fail to compare enumerable of strings
-
22-04-2021 - |
質問
This code works fine
[Test]
public void boo()
{
var collection = new[] { 1, 2, 3 };
collection.Should().Equal(1, 2, 3);
}
But, this fails
[Test]
public void foo()
{
var collection = new[] { "1", "2", "3" };
collection.Should().Equal("1", "2", "3");
}
The failure message is:
'Expected collection to be equal to {1} because 2, but {"1", "2", "3"} contains 2 item(s) too many.'
What is wrong here? Why enumerable of string could not be compared?
And, of cause, my question is - how to handle case in foo() ?
解決
This happens because the compiler selects the wrong overload of Equals() because of limitations in C#. In your particular case, it's taking the Equals(string expected, string reason, params string[] args), instead of Equals(IEnumerable). I have never found an easy way to solve this ambiguity in FluentAssertions.
To solve your problem, wrap the expected values in an array.
[Test]
public void foo()
{
var collection = new[] { "1", "2", "3" };
collection.Should().Equal(new[] {"1", "2", "3"});
}
他のヒント
The problem is that the 2nd call is resolved to the following overload:
public AndConstraint<TAssertions> Equal(IEnumerable expected,
string reason,
params object[] reasonArgs);
Instead of:
public AndConstraint<TAssertions> Equal(params object[] elements);
To get the desired result you can force the compiler to the right overload method, for example by doing:
collection.Should().Equal((object)"1", "2", "3");
What happens with the test of:
[Test]
public void foo()
{
const string one = "1";
const string two = "2";
const string three = "3";
var collection = new[] { one, two, three };
collection.Should().Equal(one, two, three);
}
I assume as Kenny acknowledged in a comment that you're doing reference equality where those strings are not the same reference.
Try SequenceEquals instead?
http://msdn.microsoft.com/en-us/library/bb342073.aspx
And the Equals method is just comparing the references for equality.
Here's a line from a unit test in one of my projects:
Assert.IsTrue(expected.OrderBy(x => x).SequenceEqual(actual.OrderBy(x => x)));
All of the elements in "expected" and "actual" implement IEQuatable.