2015-08-11 21 views
5

Tôi đang viết Bài kiểm tra đơn vị và suy nghĩ về kịch bản của loại thực hiện IClonable. Vì vậy, tất nhiên tôi muốn có một bài kiểm tra đơn vị kiểm tra phương pháp Clone().Bài kiểm tra đơn vị: Clone và equality

[Test] 
public void CloneObject() 
{ 
    MyType original = new MyType(); 
    MyType clone = (MyType)original.Clone(); 

    // Assert for equality 
} 

Vì vậy, nhiệm vụ đầu tiên của tôi là có Assert cho sự bình đẳng. Tôi thấy các tùy chọn sau đây:

  • đi qua tất cả các thuộc tính (trường) của MyType và kiểm tra từng cái một
  • override Equals() trong MyType để cho MyType nói nếu hai trường hợp đều bình đẳng (xem xét rằng đôi khi sự bình đẳng cho các bài kiểm tra là được xem là khác nhau về bình đẳng đối với mã sản xuất)
  • Kiểm tra với một số loại tuần tự nếu các trường hợp bằng nhau (cho trường hợp đó MyType sẽ phải là [Serializable], nhưng đôi khi rất khó thực hiện nếu nó có ví dụ Giao diện)
  • ... ??

Đối với hai đầu tiên tôi có thể thiết lập các thử nghiệm của mình và chúng hoạt động tốt. Nhưng nếu tôi thay đổi MyType và thêm một thuộc tính bổ sung thì sao? Nếu Clone() không sao chép điều này và tôi không thêm nó vào danh sách thuộc tính đã chọn hoặc phương thức equals thì thử nghiệm của tôi vẫn chuyển ngay cả khi thuộc tính không được sao chép.

Làm cách nào để bạn giải quyết loại thử nghiệm này?

+0

Bạn đã xem Json (de) serialization hay không mà bị những hạn chế tương tự như serialization nhị phân ('[Serializable]') trong quan điểm của bạn? –

Trả lời

5

Bạn có thể sử dụng FluentAssertions thư viện (một TDD-phải có, IMO), trong đó có một phương pháp ShouldBeEquivalent mà thực hiện graph comparison của hai đối tượng:

original.ShouldBeEquivalentTo(clone); 

Thuật toán so sánh có thể được tùy chỉnh thông qua các tùy chọn options tham số; xem wiki để biết thông tin chi tiết.

Để thực hiện các thử nghiệm tương lai chứng minh (ví dụ, nó phá vỡ khi các thuộc tính mới được bổ sung vào lớp, nhưng không với phương pháp Clone), bạn có thể muốn thử nghiệm nhân bản một đối tượng với tất cả các thuộc tính của nó thiết lập để ngẫu nhiên giá trị không mặc định. AutoFixture có thể làm điều đó cho bạn.

// Arrange 
var fixture = new Fixture(); 
var original = fixture.Create<MyType>(); 

// Act 
var clone = original.Clone(); 

// Assert 
clone.ShouldBeEquivalentTo(original); 

Liên kết hữu ích:

+0

Cảm ơn! Điều đó làm việc cho tôi :) – joerg

+0

@joerg no prob! Hãy chắc chắn để kiểm tra những gì khác bạn có thể làm với FluentAssertions - đó là đầy đủ các goodies! – dcastro

+0

Rất tiếc ... một bước trở lại ... Tôi vừa thêm 'int' vào loại của mình ... Tôi sẽ phải đặt giá trị không mặc định trong thử nghiệm của mình thành không thành công ... chỉ cần thêm thuộc tính này và thử nghiệm vẫn đi qua ... – joerg

0

tôi sẽ ủng hộ việc thực hiện Equals(). Tôi không thấy lý do tại sao Equals() cần phải tạo ra các kết quả khác nhau trong sản xuất so với trong các thử nghiệm.

Nếu bạn không làm điều đó, Khẳng định của bạn có thể gọi object.ReferenceEquals(), như sau:

Assert.IsTrue(object.ReferenceEquals(expectedObject, objectInHand)); 
+0

Tôi thấy đọc [this] (http://blog.ploeh.dk/2012/06/22/Test-specificEqualityversusDomainEquality/) rất hữu ích ... các ReferenceEquals nên Assert để sai vì clone nên có một tham chiếu khác với nguyên – joerg

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