Skip to content

Creation of failure message for BeEmpty iterates over the collection #1691

@FabianNitsche

Description

@FabianNitsche

Description

I was accidentally using GenericCollectionAssertions.BeEmpty() on an IEnumerable<T> created by Moq. The test ran for ages, so I investigated and found that the problem occurs for infinite enumerables. I know that this is hardly a use case, but I think I can provide a simple fix. The issue could also hit performance if iterating over the collection is expensive.

The problem is in EnumerableValueFormatter in line

string moreItemsMessage = $"…{collection.Count() - MaxItems} more…";

calling collection.Count(). This could be replaced by checking if value implements ICollection and using ICollection.Count. For collections that only implement the IEnumerable interface, another message is needed, that does not specify the difference in element count of the two collections.

Complete minimal example reproducing the issue

private class InfiniteEnumerable : IEnumerable<object>
{
    public IEnumerator<object> GetEnumerator() => new InfiniteEnumerator();

    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

private class InfiniteEnumerator : IEnumerator<object>
{
    public bool MoveNext() => true;

    public void Reset() { }

    public object Current => new object();

    object IEnumerator.Current => Current;

    public void Dispose() { }
}

[Fact]
public void When_asserting_an_infinite_collection_to_be_empty_it_should_throw_correctly()
{
    // Arrange
    var collection = new InfiniteEnumerable();

    // Act
    Action act = () => new InfiniteEnumerable().Should().BeEmpty();

    // Assert
    act.Should().Throw<XunitException>();
}

Expected behavior:

Assert fails, with a message, that the infinite collection is not empty.

Actual behavior:

Test fails with an overflow exception of the Count() operation.

Versions

using latest FluentAssertions and .NET Core 2.1.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions