2

For ex. I need to assert that list:

var list = new List<string> { "James", "Michael", "Tom", "John" };

Should contain a certain number (currently 2) of elements matching specific predicate:

list.Should().Contain(element => element.StartsWith("J"), 2);

But this method has no such overload. How can I do it in FluentAssertions?

Hopeless
  • 579
  • 1
  • 8
  • 25
  • URL http://www.continuousimprover.com/2012/09/asserting-object-graph-equivalence.html can help – Anil May 22 '16 at 11:20

2 Answers2

4

You can't. The closest you can get is by rewriting that line as

list.Where(element => element.StartsWith("J")).Should().HaveCount(2);

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

You can create an extension for GenericCollectionAssertions class as described here https://fluentassertions.com/extensibility/

Here is the example of assertions and tests for them:

using FluentAssertions;
using FluentAssertions.Collections;
using FluentAssertions.Execution;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
using Xunit.Sdk;

namespace FluentAssetionExtensions
{
    internal static class GenericCollectionAssertionsExtension
    {
        public static AndConstraint<GenericCollectionAssertions<T>> ContainMatching<T>(this GenericCollectionAssertions<T> assertions, Func<T, bool> predicate, string because = null, params object[] becauseArgs)
        {
            Execute.Assertion
                .BecauseOf(because, becauseArgs)
                .ForCondition(assertions.Subject.Any(predicate))
                .FailWith("Expected collection to contain at least one item matching the predicate, but it does not.");
            return new AndConstraint<GenericCollectionAssertions<T>>(assertions);
        }

        public static AndConstraint<GenericCollectionAssertions<T>> NotContainMatching<T>(this GenericCollectionAssertions<T> assertions, Func<T, bool> predicate, string because = null, params object[] becauseArgs)
        {
            Execute.Assertion
                .BecauseOf(because, becauseArgs)
                .ForCondition(!assertions.Subject.Any(predicate))
                .FailWith("Expected collection not to contain at least one item matching the predicate, but it does.");
            return new AndConstraint<GenericCollectionAssertions<T>>(assertions);
        }
    }

    public class GenericCollectionAssertionsExtensionTest
    {
        [Fact]
        public void Contains_OK()
        {
            var list = new List<int> { 1, 2, 3 };
            ((Action)(() => list.Should().ContainMatching(x => x == 1))).Should().NotThrow();
            ((Action)(() => list.Should().ContainMatching(x => x == 2))).Should().NotThrow();
            ((Action)(() => list.Should().ContainMatching(x => x == 3))).Should().NotThrow();
        }

        [Fact]
        public void Contains_Fail()
        {
            var list = new List<int> { 1, 2, 3 };
            ((Action)(() => list.Should().ContainMatching(x => x == 4))).Should().Throw<XunitException>();
        }

        [Fact]
        public void NotContains_OK()
        {
            var list = new List<int> { 1, 2, 3 };
            ((Action)(() => list.Should().NotContainMatching(x => x == 4))).Should().NotThrow();
        }

        [Fact]
        public void NotContains_Fail()
        {
            var list = new List<int> { 1, 2, 3 };
            ((Action)(() => list.Should().NotContainMatching(x => x == 2))).Should().Throw<XunitException>();
        }
    }
}