2

I am attempting to assert that a collection of Claims contains an expected set of claims. The problem that I seem to be running into is that there's no way to check for a subset and supply my own equivalency options.

var expected = new[] {
    new Claim(ClaimTypes.Name, "joshdev"),
    new Claim(ClaimTypes.Email, "test@test.com"),
    new Claim(ClaimTypes.GivenName, "Josh"),
    new Claim(ClaimTypes.Surname, "Perry"),
};

var identity = GetIdentity();

What I've tried...

identity.Claims.ShouldAllBeEquivalentTo(expected, options => options.Including(x => x.Type).Including(x => x.Value));

This fails if the identity's claims are not exactly the expected set, e.g. there are more than just those claims.

identity.Claims.Should().Contain(expected);

This fails because Contain simply uses the object::Equals method which the Claim type does not implement.

What I need is some way to do Contain but with the same equivalency options as ShouldAllBeEquivalentTo exposes. I thought perhaps ShouldBeEquivalentTo would be what I wanted, but that provides for asserting the collection object itself, not the items in the collection.

joshperry
  • 41,167
  • 16
  • 88
  • 103
  • How do you define two `Claim`s to be equal? All fields equal or just a set of "key" fields? – D Stanley Dec 17 '12 at 20:44
  • In this specific testcase "Equal" just means that the `Type` and `Value` properties are equal. (See the first assertion, `options.Including...`) Ideally I'd like to be able to provide equivalency options like `ShouldALlBeEquivalentTo` but have the semantics of `Contains`, or somehow specify something like an `IEqualityComparer`. – joshperry Dec 17 '12 at 20:47

2 Answers2

3

If you use Shouldly, you can use ShouldAllBe with Contains.

collection1 = {1, 2, 3, 4};
collection2 = {2, 4, 1, 3};

collection1.ShouldAllBe(item=>collection2.Contains(item)); // true

And finally, you can write an extension.

public static class ShouldlyIEnumerableExtensions
{
    public static void ShouldEquivalentTo<T>(this IEnumerable<T> list, IEnumerable<T> equivalent)
    {
        list.ShouldAllBe(l => equivalent.Contains(l));
    }
}

UPDATE

An optional parameter exists on ShouldBe method.

collection1.ShouldBe(collection2, ignoreOrder: true); // true
  • I've just found on [latest version](https://github.com/shouldly/shouldly/issues/340#issuecomment-166708101) that there is a parameter `bool ignoreOrder` on **ShouldBe** method. – Pier-Lionel Sgard Nov 14 '17 at 15:22
2

Unfortunately this is not yet possible in the current version. The extension points are there (see the EquivalencyValidator class), but the list of steps is currently private. Otherwise you could have replaced the EnumerableEquivalencyStep with your own implementation that provides the 'contains' behavior.

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