MbUnit: сравнение отдельных экземпляров объекта - PullRequest
4 голосов
/ 25 августа 2009

Я хотел бы знать, есть ли способ сравнить два объекта в 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 ]

7 голосов
/ 26 августа 2009

Янн также реализовал StructuralEqualityComparer, который сравнивает значения свойств по одному с учетом набора лямбд для каждого свойства. Стоит посмотреть.

Больше информации здесь: http://www.gallio.org/api/html/T_MbUnit_Framework_StructuralEqualityComparer_1.htm

4 голосов
/ 25 августа 2009

Существует перегрузка Assert.AreEqual(), которая принимает IEqualityComparer<T> в качестве параметра, а другая - EqualityComparison<T>

В противном случае вы можете использовать Assert.AreEqual(Assert.XmlSerialize(a), Assert.XmlSerialize(b))

1 голос
/ 27 августа 2009

Что я обычно делаю, так это просто реализую переопределение ToString () - что считается лучшим вариантом в любом случае.

так в вашем случае:

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

тогда ваш AreEqual(foo1,foo2) действительно сообщит правильные результаты, так как он просто вызовет реализацию ToString по умолчанию

1 голос
/ 25 августа 2009

Я бы посоветовал вам переопределить метод 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;
}
...