4

我想知道是否有一种方法可以比较 MBUnit 中的两个对象,以便在对象“看起来”相同时通过测试,即使这些对象是不同的实例?

例如:

[TestFixture]
class ComparisonTestFixture
{

    class foo
       {
           public string bar;
       }

    [Test]
    public void ComparisonTest()
    {

        foo foo1 = new foo()
           {
               bar = "baz"
           };

        foo foo2 = new foo()
            {
                bar = "baz"
            };


        //This assertion should be successful, but it isn't
        //*** Failures ***
        //Expected values to be equal.
        //Expected Value & Actual Value : {foo: bar = "zzz...."}
        //Remark : Both values look the same when formatted but they are distinct instances.
        Assert.AreEqual(foo1,foo2);
    }
}

Assert.AreEqual() 对此不起作用(测试失败,请参阅上面的源代码)。由于它指出“两个值在格式化时看起来相同,但它们是不同的实例”,我认为必须有某种方法可以在 MbUnit 中内置,而无需在我自己的代码中将对象序列化为 XML。

我是否必须为此编写自己的 Assert 扩展方法?

4

4 回答 4

7

Yann 还实现了一个 StructuralEqualityComparer,它在给定每个属性的一组 lambda 的情况下逐个比较属性值。值得一看。

更多信息在这里:http ://www.gallio.org/api/html/T_MbUnit_Framework_StructuralEqualityComparer_1.htm

于 2009-08-26T08:12:18.710 回答
4

有一个重载Assert.AreEqual()需要一个IEqualityComparer<T>as 参数,另一个需要一个EqualityComparison<T>

否则你可以使用Assert.AreEqual(Assert.XmlSerialize(a), Assert.XmlSerialize(b))

于 2009-08-25T13:16:26.123 回答
1

我建议你重写Equals你的类上的方法来执行你想要的比较。这允许您定义值相等而不是引用相等。一个警告是,GetHashCode如果您覆盖Equals以确保两个相等的对象也返回相同的哈希码,您还必须覆盖。这是一个非常简单的例子;

public class Foo {

  public String Bar {
    get;
    set;
  }

  public String Baz {
    get;
    set;
  }

  public override Boolean Equals(Object other) {
    Foo otherFoo = other as Foo;
    return otherFoo != null
      && Bar.Equals(otherFoo.Bar)
      && Baz.Equals(otherFoo.Baz);
  }

  public override Int32 GetHashCode() {
    return Bar.GetHashCode() ^ Baz.GetHasCode();
  }

}

如果您不想覆盖Equals并且您真的只想逐个比较实例属性,则可以使用反射:

public static Boolean AreEqual<T>(T a, T b) {
  foreach (PropertyInfo propertyInfo in typeof(T).GetProperties())
    if (!Object.Equals(propertyInfo.GetValue(a, null),
                       propertyInfo.GetValue(b, null)))
      return false;
  return true;
}
于 2009-08-25T11:12:49.997 回答
1

我通常做的只是实现 ToString() 覆盖——无论如何,这被认为是最佳实践。

所以在你的情况下:

public override string ToString()
{
    return string.Format("Class foo, bar={0}",bar);
}

那么您AreEqual(foo1,foo2)实际上会报告正确的结果,因为它只会调用默认的 ToString 实现

于 2009-08-27T17:26:52.480 回答