I am using the DeepEqual library, to test if the results of a test match my expected output.
I do the comparison simply as
results.ShouldDeepEqual(expected);
However, I don't know how to ignore a property within my list type
The type I am deep comparing contains a list. The data type held within this list contains a Guid
property Id
which I want to ignore, as well as a date.
Ignoring top level properties works fine. However, I don't see how to ignore properties on a list type.
To get around this for now, I have had to write some code to clear these properties myself, but this is obviously not ideal.
for (var i = 0; i < results.MyList.Count; i++)
{
results.MyList[i].Id = Guid.Empty;
expectedResults.MyList[i].Id = Guid.Empty;
}
How can I accomplish this?
Having a look through the source code of DeepEqual, the library allows for custom comparisons via the IComparison
interface. With that, I simulated the models that you require:
public class MyClass
{
public MyClass()
{
MyList = new List<MySubClass>(new[]
{
new MySubClass {Id = Guid.Parse("1".PadLeft(32, '0')), Name = "Foo"},
new MySubClass {Id = Guid.Parse("2".PadLeft(32, '0')), Name = "Bar"},
new MySubClass {Id = Guid.Parse("3".PadLeft(32, '0')), Name = "Test"},
});
}
public MyClass(params MySubClass[] subs)
{
MyList = new List<MySubClass>(subs);
}
public List<MySubClass> MyList { get; set; }
}
public class MySubClass
{
public Guid Id { get; set; }
public string Name { get; set; }
}
Then I went on to creating a custom IComparison
class:
public class MySubClassComparer : IComparison
{
public bool CanCompare(Type type1, Type type2)
{
return type1 == type2 && type1 == typeof(MySubClass);
}
public (ComparisonResult result, IComparisonContext context) Compare(IComparisonContext context, object value1, object value2)
{
if (value1 is MySubClass first && value2 is MySubClass second)
{
if (first.Name == second.Name)
{
return (ComparisonResult.Pass, context);
}
}
return (ComparisonResult.Fail, context);
}
}
Here are both of my passing unit tests:
[Fact]
public void IsDeepEqual_ShouldReturnTrue_WhenListHasSameNames()
{
// Arrange
MyClass sut = new MyClass();
MyClass parameter = new MyClass(new[]
{
new MySubClass {Id = Guid.Parse("4".PadLeft(32, '0')), Name = "Foo"},
new MySubClass {Id = Guid.Parse("5".PadLeft(32, '0')), Name = "Bar"},
new MySubClass {Id = Guid.Parse("6".PadLeft(32, '0')), Name = "Test"},
});
var comparer = new ComparisonBuilder().WithCustomComparison(new MySubClassComparer()).Create();
// Act
bool result = sut.IsDeepEqual(parameter, comparer);
// Assert
Assert.True(result);
}
[Fact]
public void IsDeepEqual_ShouldReturnFalse_WhenListHasDifferentNames()
{
// Arrange
MyClass sut = new MyClass();
MyClass parameter = new MyClass(new[]
{
new MySubClass {Id = Guid.Parse("4".PadLeft(32, '0')), Name = "Foo"},
new MySubClass {Id = Guid.Parse("5".PadLeft(32, '0')), Name = "Bar"},
new MySubClass {Id = Guid.Parse("6".PadLeft(32, '0')), Name = "Fail"},
});
var comparer = new ComparisonBuilder().WithCustomComparison(new MySubClassComparer()).Create();
// Act
bool result = sut.IsDeepEqual(parameter, comparer);
// Assert
Assert.False(result);
}
Notes
This comparison should ignore the Id
property, but am unsure if this is the best way to accomplish the task. There's an IgnoreProperty method which might be better suited for the task, but couldn't see a way to get it to work currently.
If anyone has more experience then I do with the library, please let me know of better ways, and I'll update my answer accordingly.