XUnit Assertion for checking equality of objects

C#xunit.netXunit

C# Problem Overview


I am using XUnit framework to test my C# code.

Is there any assert method available in this framework which does the object comparison? My intention is to check for equality of each of the object's public and private member variables.

I tried those alternatives but seldom it works:

1) bool IsEqual = (Obj1 == Obj2)
2) Assert.Same(Obj1, Obj2) which I couldnt understand what happens internally

C# Solutions


Solution 1 - C#

I had similar issue, but then luckily I am already using

using Newtonsoft.Json;

So I just had to serialize it to json object then compare as string.

var obj1Str = JsonConvert.SerializeObject(obj1);
var obj2Str = JsonConvert.SerializeObject(obj2);
Assert.Equal(obj1Str, obj2Str );

Solution 2 - C#

FluentAssertions library has some pretty powerful comparison logic inside.

myObject.ShouldBeEquivalentTo(new { SomeProperty = "abc", SomeOtherProperty = 23 });

You can even use this to assert on part of "myObject". However, it might not help you with the private fields.

Solution 3 - C#

You need to have a custom comparer to achieve this, when you compare objects otherwise they are checked on the basis of whether they are referring to the same object in memory. To override this behavior you need to override the Equals and GetHashCode method and then you could do:

Assert.True(obj1.Equals(obj2));

Here is an MSDN page abt overloading Equals method: http://msdn.microsoft.com/en-us/library/ms173147(v=vs.80).aspx

Also apt the comment on the question: https://stackoverflow.com/questions/2734914/whats-the-difference-between-iequatable-and-just-overriding-object-equals

Solution 4 - C#

There are NuGet packages that do this for you. Here are two examples that I personally use.

  1. DeepEqual:

     object1.ShouldDeepEqual(object2);
    
  2. ExpectedObjects:

     [Fact]
     public void RetrievingACustomer_ShouldReturnTheExpectedCustomer()
     {
       // Arrange
       var expectedCustomer = new Customer
       {
         FirstName = "Silence",
         LastName = "Dogood",
         Address = new Address
         {
           AddressLineOne = "The New-England Courant",
           AddressLineTwo = "3 Queen Street",
           City = "Boston",
           State = "MA",
           PostalCode = "02114"
         }                                            
       }.ToExpectedObject();
    
    
       // Act
       var actualCustomer = new CustomerService().GetCustomerByName("Silence", "Dogood");
    
       // Assert
       expectedCustomer.ShouldEqual(actualCustomer);
     }
    

Solution 5 - C#

I know this is an old question, but since I stumbled upon it I figured I'd weigh in with a new solution that's available (at least in xunit 2.3.1 in a .net Core 2.0 solution).

I'm not sure when it was introduced, but there is now an overloaded form of .Equal that accepts an instance of IEqualityComparer<T> as the third parameter. You can create a custom comparer in your unit test without polluting your code with it.

The following code can be invoked like this: Assert.Equal(expectedParameters, parameters, new CustomComparer<ParameterValue>());

XUnit natively appears to stop processing a test as soon as a failure is encountered, so throwing a new EqualException from within our comparer seems to be in line with how XUnit works out of the box.

public class CustomComparer<T> : IEqualityComparer<T>
{
    public bool Equals(T expected, T actual)
    {
        var props = typeof(T).GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);
        foreach (var prop in props)
        {
            var expectedValue = prop.GetValue(expected, null);
            var actualValue = prop.GetValue(actual, null);
            if (!expectedValue.Equals(actualValue))
            {
                throw new EqualException($"A value of \"{expectedValue}\" for property \"{prop.Name}\"",
                    $"A value of \"{actualValue}\" for property \"{prop.Name}\"");
            }
        }

        return true;
    }

    public int GetHashCode(T parameterValue)
    {
        return Tuple.Create(parameterValue).GetHashCode();
    }
}

Edit: I found that comparing the actual and expected values with != was not effective for certain types (I'm sure there's a better explanation involving the difference between reference types and value types, but that's not for today). I updated the code to use the .Equals method to compare the two values and that seems to work much better.

Solution 6 - C#

Here is another implementation of the IEqualityComparer interface with a really GenericComparer

And for asserting that 2 lists of same type are equal, regardless of the list container, you can add this extension:

public static bool IsEqualTo<T>(this IEnumerable<T> list, IEnumerable<T> expected) where T : class
{
	if (!list.HasSameLengthThan<T>(expected))
		return false;

	Assert.Equal(expected, list, new GenericComparer<T>());
	return true;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioninquisitiveView Question on Stackoverflow
Solution 1 - C#The IntegratorView Answer on Stackoverflow
Solution 2 - C#Adrian PetrescuView Answer on Stackoverflow
Solution 3 - C#Baz1ngaView Answer on Stackoverflow
Solution 4 - C#maracuja-juiceView Answer on Stackoverflow
Solution 5 - C#Engineer_AndrewView Answer on Stackoverflow
Solution 6 - C#Islem BEZZARGAView Answer on Stackoverflow