Search code examples
c#tddfluent-assertionsobject-graph

Ignore internal properties in ShouldBeEquivalentTo


Is there a way to ignore internal properties of a class when doing ShouldBeEquivalentTo?

For example, in the class below I want to exclude the MetaData property from the object graph comparison.

public class SomeObject 
{
    Public string SomeString { get; set; }
    internal MetaData MetaData { get; set; }
}

I would prefer to not use

someObject.ShouldBeEquivalentTo(someOtherObject, options =>     
    options.Excluding(info => info.SelectedMemberPath == "MetaData")

Because I might have more than 1 internal property and setting up this for all those properties would be tedious.


Solution

  • There is the IMemberSelectionRule interface in the FluentAssertions library:

    Represents a rule that defines which members of the subject-under-test to include while comparing two objects for structural equality.

    Implementing this interface allows to exclude all the internal properties at once (where IsAssembly property is true):

      internal class AllExceptNonPublicPropertiesSelectionRule : IMemberSelectionRule
      {
        public bool IncludesMembers
        {
          get { return false; }
        }
    
        public IEnumerable<SelectedMemberInfo> SelectMembers(
          IEnumerable<SelectedMemberInfo> selectedMembers,
          ISubjectInfo context,
          IEquivalencyAssertionOptions config)
        {
          return selectedMembers.Except(
            config.GetSubjectType(context)
              .GetNonPrivateProperties()
              .Where(p => p.GetMethod.IsAssembly)
              .Select(SelectedMemberInfo.Create));
        }
      }
    

    Now the rule can be utilized in unit tests:

      someObject.ShouldBeEquivalentTo(someOtherObject, options => options.Using(
        new AllExceptNonPublicPropertiesSelectionRule()));