-
Notifications
You must be signed in to change notification settings - Fork 731
Description
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.