请参阅下面的代码:
public static class AssertEx
{
public static void PropertyValuesAreEquals(object actual, object expected)
{
PropertyInfo[] properties = expected.GetType().GetProperties();
foreach (PropertyInfo property in properties)
{
object expectedValue = property.GetValue(expected, null);
object actualValue = property.GetValue(actual, null);
if (actualValue is IList)
AssertListsAreEquals(property, (IList)actualValue, (IList)expectedValue);
else if (!Equals(expectedValue, actualValue))
Assert.Fail("Property {0}.{1} does not match. Expected: {2} but was: {3}", property.DeclaringType.Name, property.Name, expectedValue, actualValue);
}
}
private static void AssertListsAreEquals(PropertyInfo property, IList actualList, IList expectedList)
{
if (actualList.Count != expectedList.Count)
Assert.Fail("Property {0}.{1} does not match. Expected IList containing {2} elements but was IList containing {3} elements", property.PropertyType.Name, property.Name, expectedList.Count, actualList.Count);
for (int i = 0; i < actualList.Count; i++)
if (!Equals(actualList[i], expectedList[i]))
Assert.Fail("Property {0}.{1} does not match. Expected IList with element {1} equals to {2} but was IList with element {1} equals to {3}", property.PropertyType.Name, property.Name, expectedList[i], actualList[i]);
}
}
我从这里得到这个:比较NUnit中两个对象之间的相等性(Juanmas的答案(
假设我有一个这样的界面:
public interface IView
{
decimal ID { get; set; }
decimal Name { get; set; }
}
然后我有两个这样的观点:
IView view = new FormMain();
IView view2 = new FormMain();
然后,视图和视图 2 被赋予属性。
然后我想比较接口,所以我这样做:
Assert.AreEqual(Helper.PropertyValuesAreEquals(view, view2), true);
但是,这会产生一个异常:
"找不到属性获取方法。"
如何确保此函数仅获取接口中属性的属性?
我甚至应该对这样的视图进行单元测试吗?
当您拥有仅具有 setter 的属性时,会发生Property Get method was not found.
错误,例如 int MyProperty { set { x = value; } }
.
因此,您只需在PropertyValuesAreEquals
方法中跳过这些属性。
如果只想检查属于特定接口的属性,则必须将方法更改为如下所示:
public static void PropertyValuesAreEquals<T> (T actual, T expected)
{
PropertyInfo[] properties = typeof (T).GetProperties ();
//...
}
现在我们可以运行此方法:PropertyValuesAreEquals<IView> (view, view2);
不要忘记<IView>
参数;否则编译器可能会使用FormMain
类型作为泛型类型参数。
您可以考虑使用泛型,在上面的逻辑中,您应该检查属性是否存在于提供的两个对象中并且可以读取。
public static void PropertyValuesAreEquals<T>(T actual, T expected)
where T : class {
var properties = typeof(T).GetProperties().Where(p => p.CanRead);
foreach (var property in properties) {
var expectedValue = property.GetValue(expected, null);
var actualValue = property.GetValue(actual, null);
if (actualValue is IList)
AssertListsAreEquals(property, (IList)actualValue, (IList)expectedValue);
else if (!Equals(expectedValue, actualValue))
Assert.Fail("Property {0}.{1} does not match. Expected: {2} but was: {3}", property.DeclaringType.Name, property.Name, expectedValue, actualValue);
}
}
并在您的情况下用作
Assert.IsTrue(Helper.PropertyValuesAreEquals<IView>(view, view2));
您还可以使用泛型函数,而无需指定"实际"和"预期"的类型。
public static void PropertyValuesAreEquals<T>(object actual, object expected)
{
Assert.IsTrue(actual is T);
Assert.IsTrue(expected is T);
foreach (var property in typeof(T).GetProperties().Where(o => o.CanRead))
{
var actualValue = property.GetValue(actual, null);
var expectedValue = property.GetValue(expected, null);
...
}
}