假设我想使用此签名对方法进行单元测试:
List<MyItem> getMyItems();
假设MyItem
是一个包含许多属性的Pojo,其中一个属性为"name"
,可通过getName()
访问。
我关心验证的是List<MyItem>
或任何Iterable
包含两个MyItem
个实例,其"name"
个属性的值为"foo"
和"bar"
。如果任何其他属性不匹配,我真的不关心此测试的目的。如果名称匹配,则表示测试成功。
如果可能,我希望它是单行的。这是我想要做的事情的一些“伪语法”。
assert(listEntriesMatchInAnyOrder(myClass.getMyItems(), property("name"), new String[]{"foo", "bar"});
Hamcrest对这类事情有好处吗?如果是这样,我上面的伪语法的hamcrest版本究竟是什么?
答案 0 :(得分:106)
谢谢@Razvan,他指出了我正确的方向。我能够在一条线上获得它并且我成功地追捕了Hamcrest 1.3的进口。
进口:
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;
代码:
assertThat( myClass.getMyItems(), contains(
hasProperty("name", is("foo")),
hasProperty("name", is("bar"))
));
答案 1 :(得分:46)
尝试:
assertThat(myClass.getMyItems(),
hasItem(hasProperty("YourProperty", is("YourValue"))));
答案 2 :(得分:38)
它不是特别的Hamcrest,但我认为值得一提。我在Java8中经常使用的是:
assertTrue(myClass.getMyItems().stream().anyMatch(item -> "foo".equals(item.getName())));
(编辑Rodrigo Manyari的轻微改进。它的冗长一点。请参阅评论。)
阅读可能有点困难,但我喜欢类型和重构安全性。 它对于组合测试多个bean属性也很酷。例如与类似Java的&amp;&amp;过滤器lambda中的表达式。
答案 3 :(得分:18)
Assertj擅长这一点。
import numpy as np
import pandas as pd
from xlsxwriter.utility import xl_range
writer = pd.ExcelWriter('test.xlsx', engine='xlsxwriter')
workbook = writer.book
df = pd.DataFrame({'Data': np.random.rand(255)})
df.to_excel(writer, 'TEST')
test_sheet = writer.sheets['TEST']
chart = workbook.add_chart({'type': 'scatter'})
chart.add_series(
{
'name': 'Rand',
'marker': {
'type': 'circle',
'size': 2,
'fill': {'color': '#008000'},
'border': {'none': True},
},
'line': {'none': True},
'categories': "=TEST!{}".format(xl_range(1, 0, 255, 0)),
'values': "=TEST!{}".format(xl_range(1, 1, 255, 1))
}
)
test_sheet.insert_chart('C1', chart)
writer.close()
与hamcrest相比,assertj的大优点是易于使用代码完成。
答案 4 :(得分:7)
AssertJ在UserStatus
中提供了一项出色的功能:您可以传递POCO
来提取字段。它在编译时提供检查。
您也可以先声明大小。
它将给出:
extracting()
Function
断言,无论顺序如何,列表仅包含这些值。
要断言该列表包含这些值(无论顺序如何,但可能还包含其他值),请使用import static org.assertj.core.api.Assertions;
Assertions.assertThat(myClass.getMyItems())
.hasSize(2)
.extracting(MyItem::getName)
.containsExactlyInAnyOrder("foo", "bar");
:
containsExactlyInAnyOrder()
答案 5 :(得分:4)
只要你的List是一个具体的类,只要你在MyItem上实现了equals()方法,就可以简单地调用contains()方法。
// 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")));
假设您已经实现了一个接受您想要断言的值的构造函数。我意识到这不是一行,但知道缺少哪个值而不是一次检查两个值是有用的。
答案 6 :(得分:0)
AssertJ 3.9.1支持anyMatch
方法中的直接谓词用法。
assertThat(collection).anyMatch(element -> element.someProperty.satisfiesSomeCondition())
这通常适用于任意复杂的情况。
对于简单的情况,我更喜欢使用extracting
方法(请参见上文),因为生成的可迭代的被测对象可能支持具有更好可读性的值验证。
示例:它可以在Frank Neblung的答案中提供专门的API,例如contains
方法。或者您也可以稍后再调用anyMatch
并使用诸如"searchedvalue"::equals
之类的方法引用。也可以将多个提取器放入extracting
方法中,然后使用tuple()
验证结果。
答案 7 :(得分:0)
除了hasProperty
以外,您还可以尝试使用具有提取功能的hamcrest-more-matchers where
匹配器。就您而言,它看起来像:
import static com.github.seregamorph.hamcrest.MoreMatchers.where;
assertThat(myClass.getMyItems(), contains(
where(MyItem::getName, is("foo")),
where(MyItem::getName, is("bar"))
));
这种方法的优点是:
Expected: iterable containing [Object that matches is "foo" after call
MyItem.getName, Object that matches is "bar" after call MyItem.getName]
but: item 0: was "wrong-name"