Bộ so sánh JUnit 4


102

Làm thế nào bạn có thể khẳng định một cách ngắn gọn sự bình đẳng của Collectioncác phần tử, cụ thể là a Settrong JUnit 4?



Bạn đang cố gắng khẳng định rằng hai Tập hợp là bằng nhau (chứa các phần tử giống nhau), hay hai phần tử của cùng một Tập hợp là bằng nhau?
Bill the Lizard

Tôi cần thấy rằng các phần tử của hai Bộ là bằng nhau
Eqbal 22/02/1010

Câu trả lời:


103

Bạn có thể khẳng định rằng hai Sets bằng nhau, điều này gọi ra Set equals()phương thức .

public class SimpleTest {

    private Set<String> setA;
    private Set<String> setB;

    @Before
    public void setUp() {
        setA = new HashSet<String>();
        setA.add("Testing...");
        setB = new HashSet<String>();
        setB.add("Testing...");
    }

    @Test
    public void testEqualSets() {
        assertEquals( setA, setB );
    }
}

Điều này @Testsẽ vượt qua nếu hai Sets có cùng kích thước và chứa các phần tử giống nhau.


7
Điều này không hiển thị kết quả rất tốt trong báo cáo. Nếu toStrings của bạn được xác định rõ ràng nó là tốt hơn, nhưng vẫn không tốt (A chênh lệch nhỏ có thể kết thúc với một trang văn bản)
Bill K

Uhm, làm sao mà tôi nhận được: java.lang.AssertionError: mong đợi: java.util.Hashtable <{CompanyName = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, Category = AvrIfd, QuoteId = 43426940 = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, Category = AvrIfd, QuoteId = 4342740204922826921}>
Giovanni Botta

3
@Giodude Bạn có equalshashCodetriển khai trong lớp mà bạn đang lưu trữ trong Hashtable không?
Bill the Lizard

Như bạn có thể thấy đó chỉ là những chuỗi và một đoạn dài ... Tôi đang thử nghiệm Avro để tuần tự hóa và hủy tuần tự hóa một bản đồ và đó là kết quả. Tôi nghĩ rằng chắc chắn có điều gì đó khó hiểu đang xảy ra với cách các chuỗi được nối tiếp và hủy tuần tự khiến bài kiểm tra không thành công nhưng tôi dường như không thể tìm ra vấn đề.
Giovanni Botta

Không hiệu quả với tôi mặc dù tôi đang so sánh hai HashSet <Dài>. Câu trả lời @MattFriedman thực sự phù hợp với trường hợp sử dụng của tôi.
bluecollarcoder

46

Apache lại tham gia giải cứu.

assertTrue(CollectionUtils.isEqualCollection(coll1, coll2));

Hoạt động như một sự quyến rũ. Tôi không biết tại sao nhưng tôi thấy rằng với các bộ sưu tập sau đây assertEquals(coll1, coll2)không phải lúc nào cũng hoạt động. Trong trường hợp nó không thành công với tôi, tôi có hai bộ sưu tập được hỗ trợ bởi Bộ. Cả hamcrest và junit đều không nói rằng các bộ sưu tập là bằng nhau mặc dù tôi biết chắc rằng chúng là như vậy. Sử dụng CollectionUtils nó hoạt động hoàn hảo.


20
Đây thực sự là không đáng kể, một phần khó khăn là để chỉ rõ sự khác biệt cho người gọi
Bill K

1
Câu trả lời được chấp nhận là một câu trả lời tốt cho câu hỏi ban đầu (bài kiểm tra đơn vị cụ thể cho hai Bộ) nhưng câu trả lời này với CollectionUtils là câu trả lời tốt hơn cho trường hợp chung nhất. Tôi không thể so sánh Bộ sưu tập và Bộ trừ khi sử dụng CollectionUtils.
Jay,

16

với hamcrest :

assertThat(s1, is(s2));

với khẳng định rõ ràng:

assertEquals(s1, s2);

NB: t phương thức equals () của lớp tập hợp cụ thể được sử dụng


1
Tôi thích phương pháp này hơn vì Hamcrest đi kèm với JUnit 4 nên không cần các thư viện khác.
JRSofty

2
Điều này có thể không hoạt động khi các bộ có các loại khác nhau.
Hans-Peter Störr

7

Một trường hợp đặc biệt thú vị là khi bạn so sánh

   java.util.Arrays$ArrayList<[[name,value,type], [name1,value1,type1]]> 

   java.util.Collections$UnmodifiableCollection<[[name,value,type], [name1,value1,type1]]>

Cho đến nay, giải pháp duy nhất mà tôi thấy là thay đổi cả hai thành bộ

assertEquals(new HashSet<CustomAttribute>(customAttributes), new HashSet<CustomAttribute>(result.getCustomAttributes()));

Hoặc tôi có thể so sánh chúng từng phần tử.


Trên thực tế, có một số giải pháp cho điều đó được trình bày trong các câu trả lời khác. Dù sao thì các bộ cũng hơi đáng tiếc cho điều này, vì chúng bỏ qua thứ tự. Có lẽ ArrayList?
Hans-Peter Störr

4

Là một phương thức bổ sung dựa trên mảng ... bạn có thể xem xét sử dụng xác nhận mảng không có thứ tự trong junitx. Mặc dù ví dụ Apache CollectionUtils sẽ hoạt động, nhưng cũng có một loạt các phần mở rộng khẳng định chắc chắn ở đó:

Tôi nghĩ rằng

ArrayAssert.assertEquivalenceArrays(new Integer[]{1,2,3}, new Integer[]{1,3,2});

phương pháp tiếp cận sẽ dễ đọc và dễ gỡ lỗi hơn cho bạn (tất cả các Bộ sưu tập đều hỗ trợ toArray (), vì vậy sẽ đủ dễ dàng để sử dụng các phương thức ArrayAssert.

Tất nhiên nhược điểm ở đây là, junitx là một tệp jar bổ sung hoặc mục nhập maven ...

 <dependency org="junit-addons" name="junit-addons" rev="1.4"/>

2

Kiểm tra bài viết này . Một ví dụ từ đó:

@Test  
public void listEquality() {  
    List<Integer> expected = new ArrayList<Integer>();  
    expected.add(5);  

    List<Integer> actual = new ArrayList<Integer>();  
    actual.add(5);  

    assertEquals(expected, actual);  
}  

ngắn nhưng rất Link, giải thích rất nhanh những gì bạn có thể làm với Junit4-
Johannes

1
Liên kết bị hỏng. Bất kỳ cơ hội nào bạn có thể tìm thấy một phiên bản lưu trữ trực tuyến hoặc tóm tắt nội dung của nó?
pzp

1

Sử dụng Hamcrest:

assertThat( set1, both(everyItem(isIn(set2))).and(containsInAnyOrder(set1)));

Điều này cũng hoạt động khi các tập hợp có kiểu dữ liệu khác nhau và báo cáo về sự khác biệt thay vì chỉ bị lỗi.


2
Nhập isIn là gì? IntelliJ không thể giải quyết việc nhập với bất kỳ gói hamcret nào.
fabien

0

Nếu bạn muốn kiểm tra xem một Danh sách hoặc Tập hợp có chứa một tập hợp các giá trị cụ thể hay không (thay vì so sánh nó với một tập hợp đã tồn tại), thì phương thức toString của các tập hợp thường rất hữu ích:

String[] actualResult = calltestedmethod();
assertEquals("[foo, bar]", Arrays.asList(actualResult).toString());

List otherResult = callothertestedmethod();
assertEquals("[42, mice]", otherResult.toString());

Điều này ngắn hơn một chút so với lần đầu tiên xây dựng bộ sưu tập dự kiến ​​và so sánh nó với bộ sưu tập thực tế, đồng thời dễ viết và sửa hơn.

(Phải thừa nhận rằng đây không phải là một phương pháp đặc biệt rõ ràng và không thể phân biệt một phần tử "foo, bar" với hai phần tử "foo" và "bar". Nhưng trên thực tế, tôi nghĩ điều quan trọng nhất là viết test dễ dàng và nhanh chóng , nếu không, nhiều nhà phát triển sẽ không bị thúc ép.)


Điều này làm cho kết quả của bài kiểm tra đơn vị của bạn phụ thuộc vào việc triển khai chuỗi từ danh sách. Nếu họ quyết định thay đổi định dạng, bài kiểm tra đơn vị sẽ không hoạt động nữa. Tôi sẽ không coi điều này là an toàn.
Laurens Op 't Zandt

@ LaurensOp'tZandt Ý bạn là Oracle thay đổi định dạng của Collection.toList ()? Điều đó chắc chắn sẽ không xảy ra. Tuy nhiên, bạn đúng là không sạch. Nhưng trong thực tế, tôi ấn tượng rằng điều quan trọng nhất là viết bài kiểm tra rất dễ dàng.
Hans-Peter Störr

Tôi đồng ý, tôi nghĩ rằng phương thức toString sẽ không có khả năng xảy ra. Vì vậy, có lẽ nó sẽ tiếp tục hoạt động. Tôi chỉ muốn chỉ ra rằng đó không phải là một cách rất sạch sẽ. Nhưng quả thực nó rất dễ dàng. Một vấn đề nảy sinh là khi so sánh các tập hợp. Vì đơn đặt hàng của họ không được đảm bảo.
Laurens Op 't Zandt

0

Tôi thích giải pháp của Hans-Peter Störr ... Nhưng tôi nghĩ nó không hoàn toàn chính xác. Đáng buồn là containsInAnyOrderkhông chấp nhận một Collectiontrong số các tài liệu để so sánh với. Vì vậy, nó phải là một Collectiontrong số Matcher:

assertThat(set1, containsInAnyOrder(set2.stream().map(IsEqual::equalTo).collect(toList())))

Nhập khẩu là:

import static java.util.stream.Collectors.toList;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.assertThat;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.