当列表内容无序时 AssertEquals
AssertEquals when list content is unordered
如果产品可以按任何顺序退货,您将如何重构以下内容?
List<Product> products = get_products("test_produc");
assertEquals(products.size(),3);
assertEquals(products.get(0).getName(), "test_product1");
assertEquals(products.get(1).getName(), "test_product2");
assertEquals(products.get(2).getName(), "test_produc3");
如果可以使用流优雅地完成,那么我不接受此类建议。也欢迎 Hamcrest 建议。
您可以使用 Stream#anyMatch(Predicate filter)
:
断言布尔条件
Returns whether any elements of this stream match the provided predicate. May not evaluate the predicate on all elements if not necessary for determining the result. If the stream is empty then false
is returned and the predicate is not evaluated.
assertEquals(products.size(), 3);
assertTrue(products.stream().anyMatch(p -> "test_product1".equals(p.getName())));
assertTrue(products.stream().anyMatch(p -> "test_product2".equals(p.getName())));
assertTrue(products.stream().anyMatch(p -> "test_product3".equals(p.getName())));
您可以使用 stream
尝试类似的操作(我假设您只对 getName
感兴趣,而我没有使用过 hamcrest,所以只使用普通的 assertTrue
) :
List<String> productNames = products.stream()
.map(p -> p.getName())
.collect(Collectors.toList());
assertTrue(productNames.contains("test_product1"));
assertTrue(productNames.contains("test_product2"));
assertTrue(productNames.contains("test_product3"));
我建议使用 AssertJ -
import static org.assertj.core.api.Assertions.assertThat;
// ......
List<String> products = get_products("test_produc").stream()
.map(Product::getName)
.collect(toList());
assertThat(products).containsExactlyInAnyOrder("Third", "Second", "First");
另外还为您提供了更多流畅的断言(尤其是 the exception handling ones)。
我会将 Abubakkar 的答案与 Hamcrest compare collections
结合起来
List<String> productNames = products.stream()
.map(p -> p.getName())
.collect(Collectors.toList());
// assert that the actual list does not contain additional elements:
assertEquals(products.size(),3);
assertThat(productNames, containsInAnyOrder("test_product1", "test_product2", "test_produc3"));
请注意,assertEquals
也可以直接作用于列表和集合。这大大减少了输入,并且会给出非常清楚的错误信息。
如果 return 值不允许包含重复项,它们应该 return 一个集合而不是一个列表。如果你可以改变你正在测试的功能,你可以按如下方式测试它:
assertEquals(new HashSet<>(Arrays.asList("Item1", "Item2")), get_products());
如果这不是一个选项,您应该对预期结果和实际结果进行排序并比较它们:
asssertEquals(Arrays.sort(Arrays.asList("Item1", "Item2")), Arrays.sort(get_products()));
最后你可以使用 Hamcrest 匹配器(函数 containsInAnyOrder
在 org.hamcrest.collection.IsIterableContainingInAnyOrder
中):
assertThat(get_products(), containsInAnyOrder("Item1", "Item2"));
在那种情况下我更喜欢使用 assertJ。也许它会令人满意。
示例:
final List<String> actual = Arrays.asList("c", "b", "a");
final List<String> expected = Arrays.asList("a", "b", "c");
Assertions.assertThat(actual).containsOnlyElementsOf(expected);
不了解 Hamcrest,我的解决方案是对每个列表(或它们的副本,如果修改它们是不可接受的)进行排序,然后断言它们是相等的。
强度:如果列表中有重复的产品也适用(在另一个列表中需要相同的重复项)。
您可以使用流从产品列表中提取名称;其他一些答案已经说明了方法。
如果产品可以按任何顺序退货,您将如何重构以下内容?
List<Product> products = get_products("test_produc");
assertEquals(products.size(),3);
assertEquals(products.get(0).getName(), "test_product1");
assertEquals(products.get(1).getName(), "test_product2");
assertEquals(products.get(2).getName(), "test_produc3");
如果可以使用流优雅地完成,那么我不接受此类建议。也欢迎 Hamcrest 建议。
您可以使用 Stream#anyMatch(Predicate filter)
:
Returns whether any elements of this stream match the provided predicate. May not evaluate the predicate on all elements if not necessary for determining the result. If the stream is empty then
false
is returned and the predicate is not evaluated.
assertEquals(products.size(), 3);
assertTrue(products.stream().anyMatch(p -> "test_product1".equals(p.getName())));
assertTrue(products.stream().anyMatch(p -> "test_product2".equals(p.getName())));
assertTrue(products.stream().anyMatch(p -> "test_product3".equals(p.getName())));
您可以使用 stream
尝试类似的操作(我假设您只对 getName
感兴趣,而我没有使用过 hamcrest,所以只使用普通的 assertTrue
) :
List<String> productNames = products.stream()
.map(p -> p.getName())
.collect(Collectors.toList());
assertTrue(productNames.contains("test_product1"));
assertTrue(productNames.contains("test_product2"));
assertTrue(productNames.contains("test_product3"));
我建议使用 AssertJ -
import static org.assertj.core.api.Assertions.assertThat;
// ......
List<String> products = get_products("test_produc").stream()
.map(Product::getName)
.collect(toList());
assertThat(products).containsExactlyInAnyOrder("Third", "Second", "First");
另外还为您提供了更多流畅的断言(尤其是 the exception handling ones)。
我会将 Abubakkar 的答案与 Hamcrest compare collections
结合起来List<String> productNames = products.stream()
.map(p -> p.getName())
.collect(Collectors.toList());
// assert that the actual list does not contain additional elements:
assertEquals(products.size(),3);
assertThat(productNames, containsInAnyOrder("test_product1", "test_product2", "test_produc3"));
请注意,assertEquals
也可以直接作用于列表和集合。这大大减少了输入,并且会给出非常清楚的错误信息。
如果 return 值不允许包含重复项,它们应该 return 一个集合而不是一个列表。如果你可以改变你正在测试的功能,你可以按如下方式测试它:
assertEquals(new HashSet<>(Arrays.asList("Item1", "Item2")), get_products());
如果这不是一个选项,您应该对预期结果和实际结果进行排序并比较它们:
asssertEquals(Arrays.sort(Arrays.asList("Item1", "Item2")), Arrays.sort(get_products()));
最后你可以使用 Hamcrest 匹配器(函数 containsInAnyOrder
在 org.hamcrest.collection.IsIterableContainingInAnyOrder
中):
assertThat(get_products(), containsInAnyOrder("Item1", "Item2"));
在那种情况下我更喜欢使用 assertJ。也许它会令人满意。 示例:
final List<String> actual = Arrays.asList("c", "b", "a");
final List<String> expected = Arrays.asList("a", "b", "c");
Assertions.assertThat(actual).containsOnlyElementsOf(expected);
不了解 Hamcrest,我的解决方案是对每个列表(或它们的副本,如果修改它们是不可接受的)进行排序,然后断言它们是相等的。
强度:如果列表中有重复的产品也适用(在另一个列表中需要相同的重复项)。
您可以使用流从产品列表中提取名称;其他一些答案已经说明了方法。