仅将获取属性应用于接口



请参阅下面的代码:

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

最新更新