c# - 流畅的断言 : How to assert "single equivalent item in collection"?

标签 c# unit-testing assertion fluent-assertions

在 MSTest 单元测试中,我需要断言给定集合恰好包含与给定项目等效的单个项目,但流畅的断言似乎只支持这些方法:

items.Should().ContainEquivalentOf(item);
items.Should().ContainSingle(item);

我需要两者的组合,例如“ContainSingleEquivalentOf(item)”(这似乎不存在?)。

问题是 ContainSingle() 似乎仅使用普通的 Equals() 方法来检查等价性,而我需要的对象不支持该方法,因此我需要使用流畅断言提供的基于反射的等价性检查。但我不知道在这种情况下如何使用它。

编辑:该集合允许包含不符合我的条件的任意其他项目。

最佳答案

没有内置方法可以断言集合恰好包含一个等价项。 但由于 Fluent Assertions 的可扩展性,我们可以构建它。

这是 ContainSingleEquivalentOf 的原型(prototype)。 但它有一些局限性。 例如。 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>();
    }
}

关于c# - 流畅的断言 : How to assert "single equivalent item in collection"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69375921/

相关文章:

c# - 如何使用 Microsoft fakes 填充在测试函数中多次调用的类

visual-c++ - 断言不是从发布版本中编译出来的

c# - 从 MS SQL Server 获取自动编号主键

c# - 使用 AttributeRouting 在 URL 中隐藏区域

c# - 解压会抛出 "The underlying compression routine could not be loaded correctly"

javascript - 为相等数组编写正确的断言测试

javascript - 将 mocha+chai 与 co 一起使用

c# - C#中字符串前面的@是什么?

unit-testing - Common Lisp 的持续集成?

javascript - 单元测试中的变量范围问题