MbUnit:比较不同的对象实例

时间:2009-08-25 11:09:34

标签: c# serialization mbunit

我想知道是否有办法比较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 个答案:

答案 0 :(得分:7)

Yann还实现了一个StructuralEqualityComparer,它给出了每个属性的一组lambdas,逐个比较属性值。值得一看。

此处有更多信息:http://www.gallio.org/api/html/T_MbUnit_Framework_StructuralEqualityComparer_1.htm

答案 1 :(得分:4)

有一个overload of Assert.AreEqual()IEqualityComparer<T>作为参数,另一个采用EqualityComparison<T>

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

答案 2 :(得分: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;
}

答案 3 :(得分:1)

我通常做的只是实现ToString()覆盖 - 这被认为是最好的做法。

所以在你的情况下:

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

然后你的AreEqual(foo1,foo2)将实际报告正确的结果,因为它只会调用默认的ToString实现