2009-08-25 5 views
4

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() (, 테스트가 실패 위의 소스 코드를 참조)이 작동하지 않습니다. "두 값 모두 형식이 같지만 별개의 인스턴스입니다."라고 말한 이후로 내 자신의 코드에서 XML로 객체를 직렬화하지 않고 MbUnit에 내장 된 방법이 있어야합니다.

내 자신의 Assert 확장 메서드를 작성해야합니까?

답변

1

원하는 비교를 수행하려면 클래스의 Equals 메서드를 재정의하는 것이 좋습니다. 이를 통해 참조 평등 대신 값 평등을 정의 할 수 있습니다. 한 가지주의 할 점은 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(); 
    } 

} 

는 :

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; 
} 
+0

를 호출하지만 그건 일반적인되지 않을 것 같은 실제로 올바른 결과를보고합니다. 내가 테스트 할 때마다이 작업을 수행해야합니다. –

+0

하지만 분명히 클래스는 가치 평등을 사용하고 참조 평등을 사용하지 않습니다. 이 사실을 포착하려면 '평등'을 무시하는 것이 좋습니다. 이는 테스트뿐만 아니라 애플리케이션 코드에도 도움이 될 수 있습니다. –

+0

실제 응용 프로그램에서는이 개체 유형의 두 인스턴스를 비교할 필요가 없습니다. 만약 내가 Equals를 오버라이드한다면, 그것은 유닛 테스트에만 해당 될 것입니다. 단위 테스트를위한 오버 헤드 코드를 최소한으로 유지하는 것이 좋습니다. –

4

매개 변수와 같은 IEqualityComparer<T>을 취하는 overload of Assert.AreEqual()있다 EqualityComparison<T>

을 소요하는 또 다른 그렇지 않으면 사용할 수 Assert.AreEqual(Assert.XmlSerialize(a), Assert.XmlSerialize(b))

+0

예,하지만 장점은 어디입니까? 나는 여전히 내 자신의 EqualityComparioson 객체를 구현해야 할 것이다. 나는 equals를 오버로딩하거나 Assert에 확장 메소드를 추가하는 것에 비해 이점이 없다. –

+0

다른 옵션을 추가했습니다 –

+0

두 번째 옵션은 내가 시도한 것입니다.대부분의 경우에는 정상적으로 작동하지만 Ninject가 백그라운드에서 사용되기 때문에 더 많은 객체에 대한 직렬화가 실패합니다. 그게 내가이 스레드를 시작하게 만든 이유입니다. –

7

Yann은 각 속성에 대해 람다 세트가 주어진 속성 값을 하나씩 비교하는 StructuralEqualityComparer도 구현했습니다. 가치가있는보고. 여기

상세 정보 : http://www.gallio.org/api/html/T_MbUnit_Framework_StructuralEqualityComparer_1.htm 나는 보통 단지 있으며, toString() 재정의 구현합니까 무엇

+0

예. Jeff가 말했듯이, 구조상 평등 비교자는이 경우에 사용할 올바른 도구입니다. IEqualityComparer를 수용하는 여러 어설 션 개체는 매개 변수 (AreEqual, AreElementsEqual 등)입니다. 비교자가 명시 적으로 동등하지 않은 형식을 비교하는 방법을 어설 션으로 지정합니다. Assert.AreEqual (foo1, foo2, new StructuralEqualityComparer {{x => x.bar}}); –

+0

간단한 사용법 샘플은 다음에서 찾을 수 있습니다. http://interfacingreality.blogspot.com/2009/06/assertdistinct-in-mbunit-v3.html –

+0

보기 좋지만 조금 성취하려고합니다. Reflexction으로 EqualityComparer를 대신 사용하겠습니다. 그래도 힌트를 주셔서 감사합니다! –

1

- 어쨌든 이렇게하는 것이 가장 최선의 방법으로 간주됩니다. 그래서 귀하의 경우

:

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

다음 AreEqual(foo1,foo2) 그냥 기본의 toString 구현

+0

이 방법이 효과가 있지만 Equals 재정의 것과 동일한 단점이 있습니다. 일반적이지는 않지만 비교해야하는 새로운 객체 유형마다 별도의 코드가 필요합니다. –