2012-10-22 22 views
9
[Test] 
public void testMultiplication() 
{ 
    var five=new Dollar(5); 
    Assert.AreEqual(new Dollar(10), five.times(2)); 
    Assert.AreEqual(new Dollar(15), five.times(3)); 
} 

lớp DollarLỗi kiểm tra NUnit? Dự kiến ​​<MyType> Nhưng là <MyType>

public class Dollar 
{ 
    private int amount; 

    public Dollar(int amount) 
    { 
     this.amount = amount; 
    } 

    public Dollar times(int multiplier) 
    { 
     return new Dollar(amount * multiplier); 
    } 

    public bool equals(Object theObject) 
    { 
     Dollar dollar = (Dollar) theObject; 

     return amount == dollar.amount; 
    } 
} 

On line Assert.AreEqual (Dollar mới (10), five.times (2)); thử nghiệm thất bại với lỗi:

dự kiến: TDDbooks.Dollar

Nhưng là: TDDbooks.Dollar

+0

sang một bên: tại sao bạn không thực hiện quá tải toán tử? –

+0

Dường như nó có thể là một vấn đề phiên bản lắp ráp; có thể bạn có hai phiên bản của assembly lắp đặt 'TDDbooks.Dollar' được tải không? –

Trả lời

4

NUnit hiển thị biểu diễn chuỗi đối tượng. Để có đầu ra thuận tiện, bạn nên ghi đè ToString phương pháp Dollar lớp:

public override string ToString() 
{ 
    return "$" + amount; 
} 

Bây giờ đầu ra sẽ như thế nào:

Expected: $10 
But was: $10 

vấn đề tiếp theo là USD so sánh. NUnit so sánh các đối tượng bằng cách gọi phương thức Equals (không phải equals, nhưng Equals. Kent Beck sử dụng Java trong ví dụ của mình. Trong C# chúng ta có đặt tên Pascal cho các phương thức). Việc thực hiện mặc định phương thức Equals trả về true nếu các đối tượng có cùng tham chiếu. Nhưng trong phương thức Times bạn tạo phiên bản mới của lớp Dollar. Để khắc phục điều đó, bạn nên thay đổi triển khai phương pháp Equals để so sánh trường số lượng.

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

    return amount == other.amount; 
} 

Cũng thông báo, bạn nên sử dụng override từ khóa để ghi đè chức năng lớp cơ sở. Và một điều nữa - khi bạn đang ghi đè chức năng Equals, bạn nên ghi đè phương thức GetHashCode. Trong trường hợp của bạn đó là OK để có cái gì đó như:

public override int GetHashCode() 
{ 
    return amount.GetHashCode(); 
} 
+2

Ngoài ra, nếu bạn có kế hoạch không lấy được từ lớp 'Dollar', hãy xem xét làm cho nó 'niêm phong'. Nếu bạn không làm cho nó 'niêm phong', hãy xem xét nói' if (GetType()! = Other.GetType()) trả về false; 'bên trong phương thức' Equals'. Nếu không, bạn có thể nhận được kết quả xấu nếu 'other' là một' Dollar' của một kiểu có nguồn gốc nhiều hơn, giống như một 'DescriptionDollar'. –

11

Phương pháp Assert.AreEquals sẽ sử dụng phương pháp Equals để kiểm tra bình đẳng. Thay vì ghi đè Object.Equals loại Dollar chỉ xác định phương thức equals mới không tham gia vào bình đẳng đối tượng .Net. Do đó nó không được sử dụng và thử nghiệm sử dụng bình đẳng tham chiếu mà không thành công. Để khắc phục điều này, bạn cần phải ghi đè các phương pháp Object.Equals

public override bool Equals(object obj) { 
    Dollar other = obj as Dollar; 
    if (other == null) { 
    return false; 
    } 

    return amount == other.amount; 
} 
0

Có một vài điều:

  1. Bạn đã xác định một phương pháp mới equals, thay vì trọng phương pháp lớp cơ sở Equals. Chuyển sang ghi đè và NUnit sẽ gọi phương thức của bạn.
  2. NUnit in đối tượng bằng cách sử dụng ToString và việc triển khai mặc định ToString là chỉ cần in tên lớp. Ghi đè ToString để in số tiền và thông báo xác nhận sẽ có ý nghĩa hơn rất nhiều.
0

gì bạn đang khẳng định có là new Dollar(10) là đối tượng giống như một five.times(2) lợi nhuận, đó là không đúng sự thật.

Nếu bạn muốn khẳng định theo cách đó bạn sẽ cần phải quá tải phương pháp Equals trong lớp Dollar của bạn như thế này:

public override bool Equals(Object obj) 
{ 
    if (obj is Dollar) 
    { 
     return this.Amount == ((Dollar)obj).Amount; 
    } 
    return false; 
} 

Bạn đang không sử dụng các từ khóa override trong phương pháp Equals của bạn.

0

Giải pháp tốt nhất đã được đưa ra bởi một vài người, nhưng có một giải pháp thay thế có thể hoạt động trong các tình huống khác. Bạn sẽ cần phải thêm một getter cho trường amount như vậy:

public int Amount { get { return amount; } } 

Và sau đó khi bạn làm bài kiểm tra đơn vị, nó sẽ trông giống như:

Assert.AreEqual(10, five.times(2).Amount); 

Vì vậy, bây giờ bạn đang so sánh một int đến một số khác int. Ngoài ra, bạn có thể đặt công khai biến số amount, mặc dù vi phạm đóng gói. Rõ ràng sử dụng phương pháp Equals đúng cách là cách tốt hơn để đi trong trường hợp này, nhưng trong một số trường hợp, điều này có thể thích hợp hơn.

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