为了实现这一点(但没有这样做)我正在反思预期和实际对象的属性并确保它们的值相等。这可以按预期工作,只要它们的属性是单个对象,即不是列表,数组,IEnumerable
...如果属性是某种类型的列表,则测试失败(在Assert.AreEqual(...)
内部for
循环)。
public void WithCorrectModel<TModelType>(TModelType expected, string error = "")
where TModelType : class
{
var actual = _result.ViewData.Model as TModelType;
Assert.IsNotNull(actual, error);
Assert.IsInstanceOfType(actual, typeof(TModelType), error);
foreach (var prop in typeof(TModelType).GetProperties())
{
Assert.AreEqual(prop.GetValue(expected, null), prop.GetValue(actual, null), error);
}
}
如果处理一个列表属性,如果我改为使用CollectionAssert.AreEquivalent(...)
,我会得到预期的结果,但这需要我转换为ICollection
,这反过来要求我知道列出的类型,我不(想)
它还要求我知道哪些属性是列表类型,我不知道如何。
那么,我应该如何断言任意类型的两个对象等效?
注意:我特意不想要要求它们相等,因为一个来自我的测试对象,一个是在我的测试类中构建的比较。
答案 0 :(得分:1)
这是有效的,不是我真正推荐的,但它有效。
const string methodName = "Boolean SequenceEqual[TSource](System.Collections.Generic.IEnumerable`1[TSource], System.Collections.Generic.IEnumerable`1[TSource])";
var sequenceEqual =
typeof(Enumerable)
.GetMethods()
.First(m => m.ToString() == methodName);
foreach (var prop in typeof(TModelType).GetProperties())
{
var expectedValue = prop.GetValue(expected, null);
var actualValue = prop.GetValue(actual, null);
foreach (var item in a.GetType().GetInterfaces())
{
if (item.IsGenericType && item.Name.Contains("IEnumerable`1"))
{
Assert.IsTrue(
(bool)sequenceEqual.MakeGenericMethod(
item.GetGenericArguments()[0]
).Invoke(null, new[] { expectedValue, actualValue })
);
}
}
}
答案 1 :(得分:1)
不确定这会顺利进行,但一种选择是将对象序列化为字节数组并进行比较。当然,假定您正在处理的对象是可序列化的。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
namespace NGTests
{
class Program
{
static void Main(string[] args)
{
Person p1 = new Person() { FirstName = "Chris", LastName = "Taylor", Children = { new Person() { FirstName = "Tamrin", LastName = "Taylor" } } };
Person p2 = new Person() { FirstName = "Chris", LastName = "Taylor", Children = { new Person() { FirstName = "Tamrin", LastName = "Taylor" } } };
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream ms1 = new MemoryStream();
formatter.Serialize(ms1, p1);
MemoryStream ms2 = new MemoryStream();
formatter.Serialize(ms2, p2);
byte[] b1 = ms1.ToArray();
byte[] b2 = ms2.ToArray();
Console.WriteLine("Objects are Equal : {0}", b1.SequenceEqual(b2));
Console.ReadKey();
}
}
[Serializable]
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Person> Children { get; private set; }
public Person()
{
Children = new List<Person>();
}
}
}