Can Fluent Assertions use a string-insensitive comparison for IEnumerable<string>?
Asked Answered
E

4

15

I've got a pair of Lists I'm trying to compare using Fluent Assertions. I can code up a comparison easily, but I'd like to use Fluent Assertions so that I can get the reason to show up in the test failed message.

Everything I've seen so far seems to using the default Object.Equals comparison, which is case-sensitive. I can't seem to pass an IComparer to the Equal or Contains methods, so is there any other way?

[TestMethod()]
public void foo()
{
  var actual = new List<string> { "ONE", "TWO", "THREE", "FOUR" };
  var expected = new List<string> { "One", "Two", "Three", "Four" };

  actual.Should().Equal(expected);
}
Ettie answered 26/3, 2012 at 18:29 Comment(0)
C
3

We could add an optional lambda expression to the Equal() method. Then, you could do something like

[TestMethod()] 
public void foo() 
{ 
   var actual = new List<string> { "ONE", "TWO", "THREE", "FOUR" }; 
   var expected = new List<string> { "One", "Two", "Three", "Four" }; 

  actual.Should().Equal(expected, 
    (o1, o2) => string.Compare(o1, o2, StringComparison.InvariantCultureIgnoreCase))
} 

A IComparer would also be possible, but I think the occasional exception to Equal()'s default behavior wouldn't warrant an additional custom-written class. In fact, a separate IComparer might ever obscure the intention of the test. Let me know what you guys think is the best solution, so I can add it as an issue on Codeplex for release 1.8.0.

Chat answered 27/3, 2012 at 6:15 Comment(3)
That's pretty much exactly what I wanted. I'll use one of the workarounds below for now, and I'll keep an eye on that next version.Ettie
The proposed solution is now implemented in the trunk and will be part of the upcoming release 2.0.0.Chat
It's now in the public beta fluentassertions.codeplex.com/releases/view/82423Chat
B
31

In later versions of Fluent Assertions, one can use following:

stringValue.Should().BeEquivalentTo(stringToCompare);

Metadata Summary

Asserts that a string is exactly the same as another string, including any leading or trailing whitespace, with the exception of the casing.

  • FluentAssertions 2.2.0.0

Which works in the version that I use.

Buckjump answered 7/4, 2014 at 8:58 Comment(1)
Now I have the opposite question: I need it to see casing differences. Am I stuck with my own handwritten comparison and then checking result being true/false?Testa
C
3

We could add an optional lambda expression to the Equal() method. Then, you could do something like

[TestMethod()] 
public void foo() 
{ 
   var actual = new List<string> { "ONE", "TWO", "THREE", "FOUR" }; 
   var expected = new List<string> { "One", "Two", "Three", "Four" }; 

  actual.Should().Equal(expected, 
    (o1, o2) => string.Compare(o1, o2, StringComparison.InvariantCultureIgnoreCase))
} 

A IComparer would also be possible, but I think the occasional exception to Equal()'s default behavior wouldn't warrant an additional custom-written class. In fact, a separate IComparer might ever obscure the intention of the test. Let me know what you guys think is the best solution, so I can add it as an issue on Codeplex for release 1.8.0.

Chat answered 27/3, 2012 at 6:15 Comment(3)
That's pretty much exactly what I wanted. I'll use one of the workarounds below for now, and I'll keep an eye on that next version.Ettie
The proposed solution is now implemented in the trunk and will be part of the upcoming release 2.0.0.Chat
It's now in the public beta fluentassertions.codeplex.com/releases/view/82423Chat
K
1

How about adding a new Fluent assertion via an extention method (or two)? I've written code to add a .EqualInsensitively(...) to the available fluent assertions for a collection of strings.

I've put the code to implement this on an external pastebin because its a little long and the MS-PL might not be compatible with CC-Wiki.

Use something like this:

private static void Main()
{
    var mylist = new List<string> {"abc", "DEF", "GHI"};
    mylist.Should().EqualInsensitively(new[] {"AbC", "def", "GHI"})
      .And.NotContain(string.Empty); //Emaple of chaining
}
Krissie answered 26/3, 2012 at 20:12 Comment(1)
the pastebin link 404sBalladist
D
0

you could wirte a extension method for IEnumerable<string> yourself (this is how I do this stuff) and I thing some Unit-Testframeworks already do so (FSUnit AFAIK)

Here is a simple example (you could improve a lot - but it should do)

public static AssertEqualSetCaseInsensitive(this IEnumerable<string> actual, IEnumerable<string> expected)
{
   if (actual.Count() != expected.Count())
      Assert.Fail("not same number of elements");

   if (!actual.All(a => expected.Any(e => e.ToLower() == a.ToLower()))
      Assert.Fail("not same sets");
}

just use like

actual.AssertEqualSetCaseInsensitive(expected);
Dilettantism answered 26/3, 2012 at 18:42 Comment(2)
"I can code up a comparison easily, but I'd like to use Fluent Assertions"Drumhead
If I do have to write code, this is probably the way I'd do it, but ideally someone is going to show me some method I hadn't seen yet in the library.Ettie

© 2022 - 2024 — McMap. All rights reserved.