我正在使用XUnit框架来测试我的C#代码。
这个框架中是否有可用于对象比较的断言方法?我的目的是检查每个对象的公共和私有成员变量是否相等。
我尝试过这些替代品,但很少有效:
1) bool IsEqual = (Obj1 == Obj2)
2) Assert.Same(Obj1, Obj2) which I couldnt understand what happens internally
答案 0 :(得分:30)
我有类似的问题,但幸运的是我已经在使用
了using Newtonsoft.Json;
所以我只需要将它序列化为json对象,然后比较为字符串。
var obj1Str = JsonConvert.SerializeObject(obj1);
var obj2Str = JsonConvert.SerializeObject(obj2);
Assert.Equal(obj1Str, obj2Str );
答案 1 :(得分:12)
您需要有一个自定义比较器来实现这一点,当您比较对象时,否则会根据它们是否引用内存中的同一对象来检查它们。要覆盖此行为,您需要覆盖Equals
和GetHashCode
方法,然后您可以执行以下操作:
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软件包可以为您完成此任务。 这是我个人使用的两个示例。
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
object1.ShouldDeepEqual(object2);
答案 4 :(得分:2)
FluentAssertions库内部具有一些非常强大的比较逻辑。
myObject.ShouldBeEquivalentTo(new { SomeProperty = "abc", SomeOtherProperty = 23 });
您甚至可以使用它在“ myObject”的一部分上进行断言。 但是,使用私有字段可能对您没有帮助。