在 FluentAssertions.Primitives.ObjectAssertions 的扩展方法中调用 Excluding 方法不起作用,但调用它正常工作

Calling Excluding method in extension method for FluentAssertions.Primitives.ObjectAssertions does not work, but calling it normally works

我已经开始在 REST 端点的集成测试中使用 FluentAssertions 库。问题是我必须比较两个实体,但不包括它们的 _id 属性。这个 属性 是从我的 IEntity 接口继承的。

public interface IEntity
{
    [BsonId]
    ObjectId _id { get; set; }
}

例如 Log class 看起来像这样

[DataContract]
public class Log : IEntity
{
    [BsonId]
    public ObjectId _id { get; set; }

    public string Message { get; set; }
}

在测试中,我像这样比较它们并且有效

retrieved.Should()
         .BeEquivalentTo(expected, options => options.Excluding(member => member._id));

但是当我将此功能提取到扩展方法以供重用时,它不起作用。它不会忽略 _id 成员。

public static class ObjectAssertionExtensions
{
    public static void BeEquivalentToExcludingId<TExpectation>(this ObjectAssertions objectAssertion, TExpectation expectation) where TExpectation : IEntity
    {
        objectAssertion.BeEquivalentTo(expectation, options => options.Excluding(member => member._id));
    }
}

当我将通用扩展方法更改为特定类型时 Log,它会正常工作。 我已经准备了带有示例 here 的最小项目。 有没有办法让这个工作正常,为什么它不能正常工作?我将尝试检查 github 存储库中 FluentAssertions 的代码。谢谢。

首先,在ObjectAssertionsExtensions中改变

是有意义的
public static void BeEquivalentToExcludingId<TExpectation>(this ObjectAssertions objectAssertion,
    TExpectation expectation) where TExpectation : IEntity

public static void BeEquivalentToExcludingId(this ObjectAssertions objectAssertion,
    IEntity expectation)

我还会将每个断言放入单独的测试中以定位问题。

事情发生是因为 BeEquivalentToExcludingId 期望 IEntity 只有 _id 属性,但是得到 Log 额外的 Message 属性.这让一切都出错了。如果它不会损害您的体系结构,只需将 IEntity 修改为 string Message 属性 即可解决问题。所以,唯一的变化:

public interface IEntity
{
    [BsonId]
    ObjectId _id { get; set; }

    string Message { get; set; }
}

解决问题。

更新:

考虑到您的评论,只需将要排除的成员设置为相同的值,调用 BeEquivalentTo 并像这样设置实际值:

public static void BeEquivalentToExcludingId(this ObjectAssertions objectAssertion, IEntity expectation)
{
    var subj = (IEntity)objectAssertion.Subject;
    var subjId = subj._id;
    var expId = expectation._id;

    subj._id = ObjectId.Empty;
    expectation._id = ObjectId.Empty;

    objectAssertion.BeEquivalentTo(expectation);

    subj._id = subjId;
    expectation._id = expId;
}

它很笨拙,但它确实有效。

问题是 Fluent Assertions 无法将通用类型 T_id 关联到具体类型 Log_id

#1077 and resolved with #1087 中报告了类似的问题。 在撰写本文时,我们尚未发布包含此修复程序的新版本。

编辑 2019-08-10:

Fluent Assertions 5.8.0 已随修复发布。