inq*_*ive 24 c# xunit xunit.net
我正在使用XUnit框架来测试我的C#代码.
这个框架中是否有可用于对象比较的断言方法?我的目的是检查每个对象的公共和私有成员变量是否相等.
我试过那些替代品但很少有效:
1) bool IsEqual = (Obj1 == Obj2)
2) Assert.Same(Obj1, Obj2) which I couldnt understand what happens internally
Run Code Online (Sandbox Code Playgroud)
小智 38
我有类似的问题,但幸运的是我已经在使用了
using Newtonsoft.Json;
Run Code Online (Sandbox Code Playgroud)
所以我只需要将它序列化为json对象然后比较为字符串.
var obj1Str = JsonConvert.SerializeObject(obj1);
var obj2Str = JsonConvert.SerializeObject(obj2);
Assert.Equal(obj1Str, obj2Str );
Run Code Online (Sandbox Code Playgroud)
Ada*_*m T 37
从 2022 年 8 月 1 日发布的 Xunit 2.4.2 开始,此功能作为 Assert.Equivalent 实现。
例子:
Assert.Equivalent(Obj1, Obj2);
Run Code Online (Sandbox Code Playgroud)
或者
Assert.Equivalent(Obj1, Obj2, strict:true)
Run Code Online (Sandbox Code Playgroud)
请参阅发行说明:https://xunit.net/releases/v2/2.4.2
小智 18
FluentAssertions库内部有一些非常强大的比较逻辑。
myObject.ShouldBeEquivalentTo(new { SomeProperty = "abc", SomeOtherProperty = 23 });
Run Code Online (Sandbox Code Playgroud)
您甚至可以使用它来断言“myObject”的一部分。但是,它可能无法帮助您处理私有字段。
Baz*_*nga 13
您需要有一个自定义比较器来实现这一点,当您比较对象时,否则将根据它们是否引用内存中的同一对象来检查它们.要覆盖此行为,您需要覆盖Equals和GetHashCode方法,然后您可以执行以下操作:
Assert.True(obj1.Equals(obj2));
Run Code Online (Sandbox Code Playgroud)
这是一个MSDN页面abt重载Equals方法:http://msdn.microsoft.com/en-us/library/ms173147( v = vs.80).aspx
同样适用于这个问题的评论:IEquatable与重写Object.Equals()之间的区别是什么?
有NuGet软件包可以为您执行此操作。这是我个人使用的两个示例。
object1.ShouldDeepEqual(object2);
Run Code Online (Sandbox Code Playgroud)[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);
}
Run Code Online (Sandbox Code Playgroud)我知道这是一个古老的问题,但是由于偶然发现了这个问题,所以我想考虑使用一个可用的新解决方案(至少在.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();
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:我发现比较实际值和期望值!=对于某些类型是无效的(我确定有更好的解释涉及引用类型和值类型之间的区别,但是今天还不行)。我更新了代码以使用该.Equals方法比较两个值,这似乎更好。