XUnit Assertion用于检查对象的相等性

时间:2012-06-21 09:31:43

标签: c# xunit.net xunit

我正在使用XUnit框架来测试我的C#代码。

这个框架中是否有可用于对象比较的断言方法?我的目的是检查每个对象的公共和私有成员变量是否相等。

我尝试过这些替代品,但很少有效:

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

5 个答案:

答案 0 :(得分:30)

我有类似的问题,但幸运的是我已经在使用

using Newtonsoft.Json;

所以我只需要将它序列化为json对象,然后比较为字符串。

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

答案 1 :(得分:12)

您需要有一个自定义比较器来实现这一点,当您比较对象时,否则会根据它们是否引用内存中的同一对象来检查它们。要覆盖此行为,您需要覆盖EqualsGetHashCode方法,然后您可以执行以下操作:

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

这是一个MSDN页面abt重载Equals方法:http://msdn.microsoft.com/en-us/library/ms173147(v=vs.80).aspx

也适用于对该问题的评论:What's the difference between IEquatable and just overriding Object.Equals()?

答案 2 :(得分:4)

我知道这是一个古老的问题,但是由于我偶然发现了它,我认为我可以使用一种可用的新解决方案(至少在.net Core 2.0中的xunit 2.3.1中)溶液)。

我不确定它何时推出,但现在有一个重载形式的.Equal接受IEqualityComparer<T>的实例作为第三个参数。您可以在单元测试中创建自定义比较器,而不会使用它来污染代码。

可以像下面这样调用以下代码:Assert.Equal(expectedParameters, parameters, new CustomComparer<ParameterValue>());

XUnit本身似乎在遇到失败后立即停止处理测试,因此从我们的比较器中抛出新的EqualException似乎与XUnit开箱即用的方式一致。

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

编辑:我发现将实际值和期望值与!=进行比较对某些类型无效(我确定有更好的解释,涉及参考类型和参考类型之间的差异)价值类型,但今天不适用)。我更新了代码以使用.Equals方法来比较这两个值,这似乎效果更好。

答案 3 :(得分:4)

有些NuGet软件包可以为您完成此任务。 这是我个人使用的两个示例。

  1. DeepEqual

    If you need to have this software first in your PATH run:
      echo 'export PATH="/usr/local/opt/openssl/bin:$PATH"' >> ~/.bash_profile
    
    For compilers to find this software you may need to set:
        LDFLAGS:  -L/usr/local/opt/openssl/lib
        CPPFLAGS: -I/usr/local/opt/openssl/include
    
  2. ExpectedObjects

    object1.ShouldDeepEqual(object2);
    

答案 4 :(得分:2)

FluentAssertions库内部具有一些非常强大的比较逻辑。

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

您甚至可以使用它在“ myObject”的一部分上进行断言。 但是,使用私有字段可能对您没有帮助。