在FluentAssertions.Primitives.ObjectAssertions的扩展方法中调用Exclusion方法不起作用,但通常可以正常工作

时间:2019-08-07 08:06:07

标签: c# nunit integration-testing extension-methods fluent-assertions

我已经在我的REST端点集成测试中开始使用FluentAssertions库。问题是我必须比较两个实体,但要排除它们的_id属性。该属性是从我的IEntity界面继承的。

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

例如Log类看起来像这样

[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的代码。谢谢。

2 个答案:

答案 0 :(得分:1)

首先,在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;
}

这很hack,但是可以。

答案 1 :(得分:1)

问题在于Fluent断言无法将通用类型_id的{​​{1}}与具体类型T的{​​{1}}关联。

#1077报告了类似的问题,并通过#1087解决了。 在撰写本文时,我们尚未发布包含此修复程序的新版本。

编辑2019-08-10:

Fluent Assertions 5.8.0已随修复程序一起发布。