2012-02-01 49 views
5

使用NUnit 2.5.9,下面的測試意外失敗:處理IEnumerable時NUnit Assert.AreNotEqual的行爲不正確<T>?

[TestFixture] 
public class FooTest 
{ 
    [Test] 
    public void Inequality() 
    { 
     var first = new Foo(new[] { 1 }, 2); 
     var second = new Foo(new[] { 1 }, 3); 

     Assert.AreNotEqual(first, second); 
    } 
} 

public struct Foo : IEnumerable<int>, IEquatable<Foo> 
{ 
    private readonly IEnumerable<int> values; 

    public int Bar { get; private set; } 

    public Foo(IEnumerable<int> values, int bar) 
     : this() 
    { 
     this.values = values; 
     Bar = bar; 
    } 

    public IEnumerator<int> GetEnumerator() 
    { 
     return values.GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 

    public bool Equals(Foo other) 
    { 
     return other.values.SequenceEqual(values) && other.Bar == Bar; 
    } 

    public override bool Equals(object obj) 
    { 
     if (ReferenceEquals(null, obj)) 
     { 
      return false; 
     } 
     if (obj.GetType() != typeof(Foo)) 
     { 
      return false; 
     } 
     return Equals((Foo)obj); 
    } 

    public override int GetHashCode() 
    { 
     unchecked 
     { 
      return ((values != null ? values.GetHashCode() : 0) * 397)^Bar; 
     } 
    } 

    public static bool operator ==(Foo left, Foo right) 
    { 
     return left.Equals(right); 
    } 

    public static bool operator !=(Foo left, Foo right) 
    { 
     return !left.Equals(right); 
    } 
} 

挖掘到NUnit的代碼,事實證明,當NUnit的遇到一個實現IEnumerable兩個對象,它只是比較了兩個集合,而忽略其他任何物體上的屬性。

這對我來說是錯誤的:對象實現特定接口的事實並不限制它只執行該角色。或者是.NET中的IEnumerable接口是一種特殊情況?或者我誤解了NUnit?

+0

+1有趣的問題 – sll 2012-02-01 11:57:19

回答

3

看起來這是NUnit中的一個錯誤,據我瞭解,它將在3.0版本中修復。下面有一個可能的解決辦法實現IComparer<T>一些討論:

+0

感謝您的信息。我將通過'Assert.IsTrue(first!= second)'來解決它暫時的問題 – Akash 2012-02-01 13:22:29

+0

@Akash:但是這並不會檢查proeprties,也可以考慮檢查'first.Bar!= second.Bar' – sll 2012-02-01 13:41:23

+1

@sll:爲什麼不呢? OP的類有一個'!='實現,調用'Equals',然後檢查'Bar'屬性以及集合的元素。 – LukeH 2012-02-01 14:33:31