2012-08-28 14 views
70

Giả sử tôi muốn kiểm tra đơn vị một phương pháp có chữ ký này:Làm cách nào để xác nhận một phần tử có thể lặp lại chứa một thuộc tính nhất định?

List<MyItem> getMyItems(); 

Giả MyItem là một POJO có nhiều tài sản, một trong số đó là "name", truy cập thông qua getName().

Tất cả tôi quan tâm về việc xác minh là List<MyItem>, hoặc bất kỳ Iterable, chứa hai MyItem trường hợp, có "name" thân hợp pháp có giá trị "foo""bar". Nếu bất kỳ thuộc tính nào khác không khớp, tôi không thực sự quan tâm đến mục đích của thử nghiệm này. Nếu tên phù hợp, đó là một thử nghiệm thành công.

Tôi muốn nó là một lớp lót nếu có thể. Đây là một số "cú pháp giả" của loại điều tôi muốn làm.

assert(listEntriesMatchInAnyOrder(myClass.getMyItems(), property("name"), new String[]{"foo", "bar"}); 

Hamcrest có phù hợp cho loại điều này không? Nếu vậy, chính xác thì phiên bản hamcrest của cú pháp giả của tôi ở trên là gì?

Trả lời

76

Cảm ơn bạn @Razvan đã chỉ cho tôi đúng hướng. Tôi đã có thể nhận được nó trong một dòng và tôi đã thành công săn lùng hàng nhập khẩu cho Hamcrest 1.3.

nhập khẩu:

import static org.hamcrest.CoreMatchers.is; 
import static org.hamcrest.Matchers.contains; 
import static org.hamcrest.MatcherAssert.assertThat; 
import static org.hamcrest.beans.HasPropertyWithValue.hasProperty; 

mã:

assertThat(myClass.getMyItems(), contains(
    hasProperty("name", is("foo")), 
    hasProperty("name", is("bar")) 
)); 
38

Hãy thử:

assertThat(myClass.getMyItems(), 
          hasItem(hasProperty("YourProperty", is("YourValue")))); 
+1

giống như một nút bên - đây là giải pháp hamcrest (không assertj) – Hartmut

3

Chừng Danh sách của bạn là một lớp bê tông, bạn chỉ có thể gọi phương thức chứa() miễn là bạn đã thực hiện bình đẳng của bạn() phương pháp trên myItem.

// given 
// some input ... you to complete 

// when 
List<MyItems> results = service.getMyItems(); 

// then 
assertTrue(results.contains(new MyItem("foo"))); 
assertTrue(results.contains(new MyItem("bar"))); 

Giả sử bạn đã triển khai một hàm tạo chấp nhận các giá trị bạn muốn khẳng định. Tôi nhận ra điều này không phải là trên một dòng, nhưng nó hữu ích để biết giá trị nào bị thiếu thay vì kiểm tra cả hai cùng một lúc.

+0

Tôi thực sự thích giải pháp của bạn, nhưng anh ấy nên sửa đổi tất cả mã đó cho thử nghiệm? –

+0

Tôi cho rằng mọi câu trả lời ở đây sẽ yêu cầu một số thiết lập thử nghiệm, thực thi phương pháp để kiểm tra và sau đó xác nhận các thuộc tính. Không có chi phí thực sự cho câu trả lời của tôi từ những gì tôi có thể nhìn thấy, chỉ có tôi có hai khẳng định trên đường biển để một xác nhận không thành công có thể xác định rõ ràng những gì giá trị là mất tích. – Brad

+0

Tốt nhất cũng nên bao gồm thông báo trong assertTrue để thông báo lỗi dễ hiểu hơn. Nếu không có một thông báo, nếu nó không thành công, JUnit sẽ chỉ ném một AssertionFailedError mà không có bất kỳ thông báo lỗi nào. Vì vậy, tốt nhất để bao gồm một cái gì đó như "kết quả nên chứa MyItem mới (\" foo \ ")". – Max

21

của nó không đặc biệt hamcrest, nhưng tôi nghĩ rằng nó đáng để đề cập đến ở đây. Những gì tôi sử dụng khá thường xuyên trong Java8 là một cái gì đó như:

assertTrue(myClass.getMyItems().stream().anyMatch(item -> "foo".equals(item.getName()))); 

(... Edited để cải thiện nhẹ Rodrigo Manyari của Đó là một chút ít verbose Xem bình luận)

Nó có thể là một chút khó khăn hơn để đọc, nhưng tôi thích loại và tái cấu trúc an toàn. Cũng rất thú vị khi thử nghiệm nhiều thuộc tính bean kết hợp. ví dụ. với một biểu tượng & & giống java trong bộ lọc lambda.

+2

Cải thiện nhẹ: assertTrue (myClass.getMyItems(). Stream(). AnyMatch (item -> "foo" .equals (item.getName()))); –

+0

@RodrigoManyari, đóng ngoặc đơn thiếu – Abdull

15

Assertj là điều tốt.

import static org.assertj.core.api.Assertions.assertThat; 

    assertThat(myClass.getMyItems()).extracting("name").contains("foo", "bar"); 

Big plus for assertj so với hamcrest là dễ sử dụng hoàn thành mã.