没有内置的方法可以断言一个集合只包含一个等价物。
但是由于 Fluent Assertions 的可扩展性,我们可以构建它。
这是ContainSingleEquivalentOf 的原型。
虽然它有一些限制。
例如。 Where(e => !ReferenceEquals(e, match.Which)) 断言它只会排除单个项目。
public static class Extensions
{
public static AndWhichConstraint<GenericCollectionAssertions<T>, T> ContainSingleEquivalentOf<T, TExpectation>(this GenericCollectionAssertions<T> parent,
TExpectation expected, string because = "", params string[] becauseArgs) => parent.ContainSingleEquivalentOf(expected, config => config, because, becauseArgs);
public static AndWhichConstraint<GenericCollectionAssertions<T>, T> ContainSingleEquivalentOf<T, TExpectation>(this GenericCollectionAssertions<T> parent,
TExpectation expected, Func<EquivalencyAssertionOptions<TExpectation>, EquivalencyAssertionOptions<TExpectation>> config, string because = "", params string[] becauseArgs)
{
var match = parent.ContainEquivalentOf(expected, config, because, becauseArgs);
var remainingItems = parent.Subject.Where(e => !ReferenceEquals(e, match.Which)).ToList();
remainingItems.Should().NotContainEquivalentOf(expected, config, because, becauseArgs);
return match;
}
}
请注意,Fluent Assertions 将使用Equals 在被期望覆盖以比较实例时。要覆盖该行为,您可以使用 ComparingByMembers 或提供匿名对象作为预期。
class MyClass
{
public int MyProperty { get; set; }
public override bool Equals(object obj) => false;
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void Force_comparing_by_members()
{
var subject = new MyClass[] { new() { MyProperty = 42 } };
var expected = new MyClass { MyProperty = 42 };
subject.Should().ContainSingleEquivalentOf(expected, opt => opt.ComparingByMembers<MyClass>());
}
[TestMethod]
public void Use_anonymous_expectation_to_compare_by_members()
{
var subject = new MyClass[] { new() { MyProperty = 42 } };
var expected = new { MyProperty = 42 };
subject.Should().ContainSingleEquivalentOf(expected);
}
[TestMethod]
public void Multiple_equivalent_items()
{
var subject = new MyClass[] { new() { MyProperty = 42 }, new() { MyProperty = 42 } };
var expected = new { MyProperty = 42 };
Action act = () => subject.Should().ContainSingleEquivalentOf(expected);
act.Should().Throw<Exception>();
}
[TestMethod]
public void No_equivalent_item()
{
var subject = new MyClass[] { new() { MyProperty = -1 } };
var expected = new { MyProperty = 42 };
Action act = () => subject.Should().ContainSingleEquivalentOf(expected);
act.Should().Throw<Exception>();
}
[TestMethod]
public void Fails_as_Fluent_Assertions_uses_overriden_Equals_method()
{
var subject = new MyClass[] { new() { MyProperty = 42 } };
var expected = new MyClass { MyProperty = 42 };
Action act = () => subject.Should().ContainSingleEquivalentOf(expected);
act.Should().Throw<Exception>();
}
}