0

I have started using FluentAssertions library in my integration tests for the REST endpoints. The problem is I have to compare two entities, but excluding their _id properties. This property is being inherited from my IEntity interface.

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

So for example Log class looks like this

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

    public string Message { get; set; }
}

In the test I am comparing them like this and it works

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

But when I extract this functionality to extension method for reuse purposes, it does not work. It does not ignore the _id member.

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));
    }
}

When I change the generic extension method to a specific type Log, then it works like it should. I have prepared minimal project with example here. Is there a way how to get this working please and why does it not work properly? I will try to check the code of FluentAssertions in github repository. Thanks.

CSDev
  • 3,177
  • 6
  • 19
  • 37
c0ntrol
  • 908
  • 2
  • 9
  • 14
  • Does it make any difference if you cast `expected` to `IEntity` before using it in `BeEquivalentTo`? – Jonas Nyrup Aug 07 '19 at 08:27
  • No, it gives me "Message: System.InvalidOperationException : No members were found for comparison. Please specify some members to include in the comparison or choose a more meaningful assertion." – c0ntrol Aug 07 '19 at 08:36
  • 1
    It could be a case of https://github.com/fluentassertions/fluentassertions/issues/1077. It's fixed in master but hasn't been released yet. – Jonas Nyrup Aug 07 '19 at 08:57

2 Answers2

1

First of all, in ObjectAssertionsExtensions it makes sense to change

public static void BeEquivalentToExcludingId<TExpectation>(this ObjectAssertions objectAssertion,
    TExpectation expectation) where TExpectation : IEntity

to

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

I'd also put each assertion into separate test to localize the problem.

The thing happens because BeEquivalentToExcludingId expects IEntity with _id property only, but gets Log with extra Message property. That makes everything go wrong. If it doesn't harm your architecture just ammend IEntity with string Message property and it will fix the thing. So, the only change:

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

    string Message { get; set; }
}

solves the problem.

Update:

Taking into account your comment, just set members to exclude to the same value, call BeEquivalentTo and set actual values back like this:

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;
}

It's hacky, but it works.

CSDev
  • 3,177
  • 6
  • 19
  • 37
  • Thanks for pointing out better extension method definition by directly using the type IEntity. However, adding the Message and all the other properties into IEntity defies its purpose and I would end up with just one class containing all the properties of the descendant classes. So this is not a viable solution. – c0ntrol Aug 07 '19 at 10:17
  • @c0ntrol, you are welcome. But I believe it could be neater. – CSDev Aug 07 '19 at 17:44
1

The problem is that Fluent Assertions fails to correlate _id of the generic type T to _id of the concrete type Log.

A similar issue was reported in #1077 and resolved with #1087. As of writing we haven't released new version containing this fix.

Edit 2019-08-10:

Fluent Assertions 5.8.0 has been released with the fix.

Jonas Nyrup
  • 2,376
  • 18
  • 25