2009-09-03 35 views
11

Tôi mới dùng thử đơn vị và NUit nói riêng. Tôi chỉ cần nhập một số ví dụ từ sách đề cập đến Java và JUnit. Nhưng tôi đang sử dụng C# thay thế.NUnit không hoạt động tốt với Assert.AreEqual

Vấn đề là: Tôi đã có một lớp học với phương pháp overriden như Equals()GetHashCode(), nhưng khi tôi đang cố gắng để so sánh hai đối tượng của lớp này với Assert.AreEqual() mã của tôi không được gọi, vì vậy tôi có được một ngoại lệ.

Assert.True(MyClass.Equals(MyClass2)) hoạt động tốt. Nhưng tôi không muốn sử dụng công trình này thay vì Assert.AreEqual(). Vấn đề có thể ở đâu?

Đây là lớp:

public class Money 
{ 
    public int amount; 
    protected string currency; 

    public Money(int amount, string currency) 
    { 
     this.amount = amount; 
     this.currency = currency; 
    } 

    public new bool Equals(object obj) 
    { 
     if (obj == null) 
      return false; 

     Money money = (Money)obj; 
     return (amount == money.amount) 
       && (Currency().Equals(money.Currency())); 
    } 

    public new int GetHashCode() 
    { 
     return (string.Format("{0}{1}", amount, currency)).GetHashCode(); 
    } 

    public static Money Dollar(int amount) 
    { 
     return new Money(amount, "USD"); 
    } 
    public static Money Franc(int amount) 
    { 
     return new Money(amount, "CHF"); 
    } 

    public Money Times(int multiplier) 
    { 
     return new Money(amount * multiplier, currency); 
    } 

    public string Currency() 
    { 
     return currency; 
    } 
} 

Và phương pháp thử nghiệm bản thân:

[TestFixture] 
public class DollarTest 
{ 
    [Test] 
    public void TestMultiplication() 
    { 
     Money five = Money.Dollar(5); 
     Assert.True(Money.Dollar(10).Equals(five.Times(2))); // ok 
     Assert.AreEqual(Money.Dollar(10), five.Times(2));  // fails 
    } 
} 
+2

bạn đã thử với công cụ ghi đè bool Equals() chưa? –

+0

@Samuel - đúng, nhưng bạn sẽ cần phải chuyển đổi công cụ sửa đổi và loại i.e. bool override công cộng Equals() – Fraser

Trả lời

30

Vấn đề là bạn đang ẩn Equals, không trọng nó. Well done - kiểm tra đơn vị của bạn đã tìm thấy một lỗi :)

Mã của bạn nên được:

public override bool Equals(object obj) 
{ 
    Money money = obj as Money; 
    if (money == null) 
     return false; 

    return (amount == money.amount && currency == money.currency); 
} 

(Điều này sẽ ngăn chặn nó ném một ngoại lệ nếu bạn cho nó loại sai, quá.)

tôi đã thực hiện các bài kiểm tra bình đẳng chuỗi đơn giản quá - điều hành quá tải có thể rất hữu ích :)

Bằng cách này, bạn gần như chắc chắn muốn:

  • Thay đổi Currency trở thành một tài sản, không phải là một phương pháp
  • Thêm một tài sản
  • Có lẽ thay đổi loại amountdecimal thay vì int
  • Làm cho lĩnh vực tư nhân và readonly
  • Seal Amount lớp
  • Thêm tình trạng quá tải của nhà điều hành cho == và! =
  • Có thể thêm quá tải nhà điều hành * để thực hiện tương tự như Times
  • chuỗi Tránh định dạng khi tính toán băm (có hàng chục câu trả lời cho thấy việc triển khai băm tốt hơn)

EDIT: Tôi vừa mới đọc lại mà bạn đang sử dụng một ví dụ từ một cuốn sách. Sách có thực sự ẩn thay vì ghi đè phương thức Equals không? Tôi đề nghị bạn nên có một cuốn sách mới, nếu có (trừ khi nó là một ví dụ có chủ ý khi nó là sai để sử dụng ẩn!) ... cuốn sách nào?

+2

Hy vọng lỗi này chứng tỏ giá trị của kiểm tra đơn vị! – RichardOD

+0

Điều này thật tuyệt vời. Tuyệt vời bắt đầu ngày mới. –

+0

yay, tôi đã đúng :) –

0

Tôi nghi ngờ vấn đề của bạn là bạn chưa ghi đè quá tải toán tử == bình đẳng. Dưới mui xe Assert.AreEqual có thể sử dụng ==.

Xem Operator Overloading Tutorial.

Cập nhật: Tôi đã chạy kiểm tra NUnit thông qua trình gỡ lỗi và thực sự sử dụng phương thức Equals chứ không phải toán tử ==.

+2

Bạn không thể ghi đè các toán tử - bạn chỉ có thể * quá tải * chúng. NUnit gần như chắc chắn * sẽ không * sử dụng các toán tử quá tải - nó phức tạp không cần thiết khi nó chỉ có thể gọi Equals ... –

1

tôi thấy nó khó hiểu mà thực hiện giao diện IEquatable, mà còn có một phương pháp

Equals(T other) 

, đặt ra cho tôi với cùng một vấn đề như mô tả ở trên.

Lý do duy nhất tôi chọn sử dụng giao diện IEquay có thể ghi đè phương thức Bằng không phải thực hiện kiểm tra loại.

Cuối cùng tôi đã phải sử dụng đoạn mã sau

public bool Equals(CustomTag other) 
{ 
    return (other.Name.Trim().ToLower() == Name.Trim().ToLower()); 
} 

public override bool Equals(object o) 
{ 
    if (o is CustomTag) 
    { 
     return Equals(o as CustomTag); 
    } 
    return false; 
} 

nhưng sau đó tôi nghĩ, tại sao không chỉ rời khỏi giao diện IEquatable cho những gì nó là gì và chỉ ghi đè lên các phương pháp Equals. (less code = better)

0

Bạn có thể viết các xác nhận giả thuyết về không gian sử dụng một thư viện có tên là Should. Nó cũng có một cú pháp thông thạo rất tốt có thể được sử dụng nếu bạn thích giao diện thông thạo. Tôi đã có một bài đăng trên blog có liên quan đến nhau.

http://nileshgule.blogspot.com/2010/11/use-should-assertion-library-to-write.html

Các vấn đề liên quan