Skip to content

Parameterless ContainSingle() evaluates IEnumerables twice #1752

@bert2

Description

@bert2

Description

The "parameterless" variant of ContainSingle() (without a predicate) evaluates IEnumerables twice. This means any side-effects in the enumerable chain are executed twice which might lead to unexpected behavior.

Complete minimal example reproducing the issue

https://dotnetfiddle.net/SFGRnc

using System.Collections.Generic;
using System.Linq;
using FluentAssertions;

var d = new Dictionary<int, int>();
var xs = new[] { 1 }
    .Select(x => {
        d.Add(x, x); // crashes if executed twice
        return x;
    });

xs.Should().ContainSingle(); // crashes
//xs.Should().ContainSingle(_ => true); // does not crash

Expected behavior:

xs.Should().ContainSingle(); should not crash.

Actual behavior:

xs.Should().ContainSingle(); crashes.

Versions

  • FluentAssertions 6.2.0
  • .NET 6.0

Additional Information

The problem is that ContainSingle() uses Count() here and also SingleOrDefault() here without materializing the enumerable first.

The variant taking a predicate does materialize the enumerable first here.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions