仅将GetProperties应用于接口

时间:2017-05-26 11:15:03

标签: c# unit-testing

请参阅以下代码:

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

我从这里接过这个:Compare equality between two objects in NUnit(Juanmas&#39;回答)

说我有这样的界面:

public interface IView
{
    decimal ID { get; set; }
    decimal Name { get; set; }
}

然后我有两个这样的观点:

IView view = new FormMain();
IView view2 = new FormMain();
然后给

view和view2赋予属性。

然后我想比较接口,所以我这样做:

Assert.AreEqual(Helper.PropertyValuesAreEquals(view, view2), true);

然而,这产生了一个例外:

  

&#34;找不到属性获取方法。&#34;。

如何确保此功能仅获取界面中属性的属性?

我是否应该对这样的视图进行单元测试?

3 个答案:

答案 0 :(得分:0)

当您拥有仅包含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类型作为泛型类型参数。

答案 1 :(得分:0)

您可以考虑使用Generics,同样在上面的逻辑中,您应该检查提供的两个对象中是否存在属性,并且可以读取。

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

答案 2 :(得分:0)

您也可以使用通用函数,而不指定“actual”和“expected”的类型。

Location:https://www.xxxxxx.com/catalog/product/view/id/1256/x