FluentAssertions: Assert Collection contains Element that "IsEquivalentTo"
Asked Answered
P

4

13

I'm stuck with what I thought was an easy example. I want to assert that a collection of objects contains an object that is equivalent to a given object. like: col.ShouldContainEquivalentTo(obj)

var objectList1 = new List<SomeClass> { new SomeClass("A"), new SomeClass("B"), new SomeClass("C") };
var objectList2 = new List<SomeClass> { new SomeClass("C"), new SomeClass("B"), new SomeClass("A") };

objectList1.ShouldAllBeEquivalentTo(objectList2); //this works
objectList2.ShouldContainEquivalentTo(new SomeClass("B")); //method does not exist. How can I achieve sthg like that

I want to compare based on the objects values - just like how ShouldBeEquivalentTo and ShouldAllBeEquivalentTo work. Should not be necessary to write my own equality comparer.

BR Matthias

Paleontology answered 28/6, 2017 at 22:24 Comment(0)
P
28

I finally had the time to implement this feature and it is now available with version 5.6.0 of FluentAssertions.

This now works!

var objectList = new List<SomeClass> { new SomeClass("A"), new SomeClass("B"), new SomeClass("C") };
objectList.Should().ContainEquivalentOf(new SomeClass("A"));

BR Matthias

Paleontology answered 12/1, 2019 at 9:25 Comment(2)
Well, now I'd like to supply an IEnumerable<SomeClass> to verify that the equivalent of all supplied objects exist.Clausius
Well, now I'd like something like dictionary.Should().ContainKeyEquivalentOf("key").WhoseValue.Should().Be("something");;Amoral
P
6

Its possible now. See accepted answer. Stop upvoting this workaround. ^^


It seems like I was too naive and there is in fact no method that does quite what I want to have. Thx @Nkosi for pointing out.

Just to round this topic up: We ended up with something like

objectList.Should().Contain(dto=>dto.Id == expectedDto.Id).Which.ShouldBeEquivalentTo(expectedDto)

This only works (edit: beautifully) when you have some kind of unique identifier (id, name, etc.). But at least it uses the build in ShouldBeEquivalentTo for all the other properties!

I created a feature request.

Thx for all the input!

BR Matthias

Paleontology answered 29/6, 2017 at 11:33 Comment(0)
R
2

You can use the already available functionality of framework to achieve the desired behavior

This is an ugly hack but should get the job done.

public static class FluentAssertionsEx {

    public static void ShouldContainEquivalentTo<T>(this IEnumerable<T> subject, object expectation, string because = "Expected subject to contain equivalent to provided object", params object[] becauseArgs) {
        var expectedCount = subject.Count();
        var actualCount = 0;
        try {
            foreach (var item in subject) {
                item.ShouldBeEquivalentTo(expectation);
            }
        } catch {
            actualCount++;
        }
        expectedCount.Should().NotBe(actualCount, because, becauseArgs);
    }
}
Rudimentary answered 28/6, 2017 at 23:8 Comment(0)
L
1

You could do something like:

objectList2.Should().Contain(x => x.Property == "B");

where Property is replaced by whichever property is set by the constructor of SomeClass.

Lookeron answered 28/6, 2017 at 22:41 Comment(3)
The "B" was just an example to demonstrate the difference. In a real scenario there would be a lot of properties. Plus, writing it like that is more or less the same as writing an equality comparer. Imho there should already be a generic solution because ShouldBeEquivalentTo and ShouldAllBeEquivalentTo already work that way.Paleontology
You can also do objectList2.Should().Contain(new SomeClass("B")) This will apply the equals on all the properties. Note that you will have to implement GetHashCode() for SomeClass. Why is it important to override GetHashCode when Equals method is overridden?Airdrome
@Paleontology do not make that assumption. That functionality does not exist at the moment. You could always raise an issue or feature request with the developer on githib.Rudimentary

© 2022 - 2024 — McMap. All rights reserved.