2009-07-07 9 views
54

Tại sao điều này không biên dịch, ồ, phải làm gì?Tại sao mã này không cố gắng sử dụng biên dịch hasItems của Hamcrest?

import static org.junit.Assert.assertThat; 
import static org.junit.matchers.JUnitMatchers.hasItems; 

ArrayList<Integer> actual = new ArrayList<Integer>(); 
ArrayList<Integer> expected = new ArrayList<Integer>(); 
actual.add(1); 
expected.add(2); 
assertThat(actual, hasItems(expected)); 

lỗi sao chép từ bình luận:

cannot find symbol method assertThat(java.util.ArrayList<java.lang.Integer>, org.hamcreset.Matcher<java.lang.Iterable<java.util.ArrayList<java.lang.Integer>>>) 

Trả lời

12

Bạn đang so sánh ArrayList<Integer> với int. Việc so sánh đúng là:

... 
assertThat(actual, hasItem(2)); 

- Edit -

Tôi xin lỗi, tôi đã đọc nó sai. Dù sao, chữ ký của hasItems bạn muốn là:

public static <T> org.hamcrest.Matcher<java.lang.Iterable<T>> hasItems(T... elements) 

tức là, nó chấp nhận số lượng đối số thay đổi. Tôi không chắc liệu ArrayList<T> có tương thích hay không, chỉ cần đoán ở đây. Thử gửi từng mục từ danh sách mong muốn xen kẽ bằng dấu phẩy.

assertThat(actual, hasItems(2,4,1,5,6)); 

- Chỉnh sửa 2 -

Chỉ cần dán ở đây nhận xét của tôi, có một biểu thức tương đương cho những gì bạn muốn, mà không sử dụng hamcrest:

assertTrue(actual.containsAll(expected)); 
+0

Tôi so sánh nhiều mặt hàng. (hasItems, not hasItem) – ripper234

+0

Vì vậy, hamcrest chỉ đơn giản là không hỗ trợ so sánh hai bộ sưu tập? (Tôi không có danh sách các mục thực tế, tôi đang tạo danh sách các số từ 0 đến 999 Tôi phải so sánh các bộ sưu tập). – ripper234

+0

Tôi không thể trả lời điều đó cho bạn, tôi đang nói điều này dựa trên tài liệu. Nhưng có một cách đơn giản hơn để làm những gì bạn muốn ... sử dụng assertTrue (actual.containsAll (mong đợi)). – freitass

2

Đó thông báo lỗi trông giống như một được sản xuất bởi trình biên dịch javac. Tôi đã tìm thấy trong quá khứ rằng mã bằng cách sử dụng hamcrest chỉ sẽ không biên dịch theo javac. Cùng một mã sẽ biên dịch tiền phạt theo trình soạn thảo Eclipse.

Tôi nghĩ rằng Generics của Hamcrest đang thực hiện các trường hợp góc trong generics mà javac không thể giải quyết được.

+0

Chà, thú vị. Vì vậy, bạn đang nói mã trên là mã java hợp pháp? – ripper234

+2

Không, tôi nói rằng javac đôi khi từ chối mã java hợp pháp, và hamcrest là một nguyên nhân phổ biến của nó. – skaffman

3

Hãy thử

assertThat(actual, hasItems(expected.toArray(new Integer[0]))); 

để đáp ứng các chữ ký khớp. Không có Eclipse xung quanh, do đó, điều này có thể không hoạt động.

21

hasItems kiểm tra xem bộ sưu tập có chứa một số mục, không phải là 2 bộ sưu tập bằng nhau, chỉ cần sử dụng xác nhận bình đẳng bình thường cho điều đó. Vì vậy, một trong hai assertEquals (a, b) hoặc sử dụng assertThat

import static org.junit.Assert.assertThat; 
import static org.hamcrest.CoreMatchers.is; 

ArrayList<Integer> actual = new ArrayList<Integer>(); 
ArrayList<Integer> expected = new ArrayList<Integer>(); 
actual.add(1); 
expected.add(2); 
assertThat(actual, is(expected)); 

Ngoài ra, sử dụng chứa Matcher, trong đó kiểm tra rằng một Iterable chứa mặt hàng theo một thứ tự cụ thể

import static org.junit.Assert.assertThat; 
import static org.hamcrest.Matchers.contains; 

ArrayList<Integer> actual = new ArrayList<Integer>(); 
actual.add(1); 
actual.add(2); 
assertThat(actual, contains(1, 2)); // passes 
assertThat(actual, contains(3, 4)); // fails 

Nếu bạn không quan tâm đến thứ tự sử dụng containsInAnyOrder thay thế.

0
ArrayList<Integer> expected = new ArrayList<Integer>(); 
expected.add(1); 
expected.add(2); 
hasItems(expected); 

hasItems (T_T) đang được mở rộng bởi trình biên dịch để:

hasItems(new ArrayList<Integer>[]{expected}); 

Bạn đang đi qua một mảng yếu tố duy nhất có chứa một ArrayList. Nếu bạn thay đổi ArrayList thành một mảng, thì mã của bạn sẽ hoạt động.

Integer[] expected = new Integer[]{1, 2}; 
hasItems(expected); 

này sẽ được mở rộng để:

hasItems(1, 2); 
1

Đối với những trường hợp này khi mã này biên dịch trong Eclipse nhưng javac thấy lỗi xin vui lòng giúp đỡ hamcrest bằng cách cung cấp một cách rõ ràng gõ tham số ví dụ Matchers.hasItem()

2

Tôi vừa bắt gặp cùng một vấn đề và cách lừa sau làm việc cho tôi:

  • sử dụng import static org.hamcrest.Matchers.hasItems
  • có thư viện hamcrest trước junit trong classpath (xây dựng đường dẫn -> trật tự và xuất khẩu)
52

Chỉ cần chạy vào bài đăng này cố tự khắc phục. Đã cho tôi đủ thông tin để làm việc đó.

Bạn có thể cung cấp cho các trình biên dịch vừa đủ để thuyết phục nó để biên dịch bằng cách đúc các giá trị trả về từ hasItems đến một (thô) Matcher, ví dụ:

ArrayList<Integer> actual = new ArrayList<Integer>(); 
ArrayList<Integer> expected = new ArrayList<Integer>(); 
actual.add(1); 
expected.add(2); 
assertThat(actual, (Matcher) hasItems(expected)); 

Chỉ trong trường hợp bất kỳ ai khác vẫn đang bị ...

Chỉnh sửa để thêm: Bất chấp số phiếu bầu lên, câu trả lời này là sai, như Arend chỉ ra bên dưới. Các đúng Câu trả lời là để biến mong đợi vào một mảng các số nguyên, như hamcrest dự kiến:

ArrayList<Integer> actual = new ArrayList<Integer>(); 
    ArrayList<Integer> expected = new ArrayList<Integer>(); 
    actual.add(1); 
    expected.add(2); 
    assertThat(actual, hasItems(expected.toArray(new Integer[expected.size()]))); 
+0

Tôi chưa thử nghiệm câu trả lời này kể từ khi tôi từ lâu đã mất mã nguồn này (các công ty chuyển hai lần), nhưng tôi đã cho bạn một ngón tay cái lên để hồi sinh điều này. – ripper234

+1

Mẹo hay. Dường như cách duy nhất "đơn giản" để sử dụng assertThat() với bất kỳ bộ sưu tập nào phù hợp kể từ khi Hamcrest thay đổi bộ sưu tập của bộ sưu tập matcher thành thay vì chỉ .. – Frans

+0

Tôi muốn 'hasItems' cũng khớp với thứ tự. Mà nó có vẻ như nó không. –

2

Bạn có thể nhận được lỗi này nếu bạn cố gắng để thay thế hamcrest JUnit với một phiên bản mới hơn. Ví dụ, sử dụng junit-dep cùng với hamcrest 1.3 yêu cầu sử dụng assertThat từ hamcrest thay vì jUnit.

Vì vậy, giải pháp là sử dụng

import static org.hamcrest.MatcherAssert.assertThat;

thay vì

import static org.junit.Assert.assertThat;