我们有一个测试套件,主要使用与Hamcrest匹配器的JUnit断言.我们的一个团队开始尝试使用AssertJ,并以其语法,灵活性和声明性来给人们留下深刻印象.JUnit提供了一个功能,我在AssertJ中找不到相应的功能:添加自定义断言失败消息.
我们经常比较那些不是为了人类可读性而且会有随机看似Ids或UUID的对象,并且不可能通过它们包含的数据来判断它们应该是什么.遗憾的是,对于我们的代码库来说,这是一个不可避免的情况,因为它实现的目的之一是在其他服务之间映射数据,而不必理解它是什么.
在JUnit中,该assertThat方法String reason在Matcher<T>param 之前提供带参数的版本.这样就可以添加一个简短的调试字符串来解决这个问题,就像比较对人类意味着什么一样.
另一方面,AssertJ提供了许多不同的泛化static assertThat方法,这些方法返回某种形式的接口Assert或其中许多实现类之一.此接口不提供设置要包含在故障中的自定义消息的标准方法.
有没有办法从AssertJ API或其扩展之一获得此功能,而无需为我们要添加消息的每个断言类型创建自定义断言类?
如何使用assertJ 检查自定义异常中的特定字段值?
这是异常类:
public class SomeException extends RuntimeException {
private final Set<Integer> something;
public SomeException (String message, Set<Integer> something) {
super(message);
this.something = something;
}
public Set<Integer> getSomething() {
return something;
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的测试:
assertThatThrownBy(() -> service.doSomething())
.isInstanceOf(SomeException.class)
.hasMessageStartingWith("SomeException has 1,2,3,4 in something field. I want assert that")
. ??? check that SomeException.getSomething() has 1,2,3,4 ???
Run Code Online (Sandbox Code Playgroud)
问题是,如果我链接extracting() ,它会认为我正在使用Throwable。所以我无法提取字段内容
更新:
SomeException throwable = (SomeException) catchThrowable(() -> service.doSomething(
assertThat(throwable)
.hasMessageStartingWith("extracting() bellow still think we're working with …Run Code Online (Sandbox Code Playgroud) 我已经在我的项目中使用AssertJ一段时间了.最近我开始使用Spring MVC Test来测试Spring MVC控制器.
但是我没有得到如何使用AssertJ.我在网上看到的所有例子都使用Hamcrest和Spring MVC Test.
下面是使用Hamcrest API的示例.
mockMvc
.perform(get("/user?operation=userList"))
.andExpect(status().isOk())
.andExpect(model().attribute(UserController.MODEL_ATTRIBUTE_USER_LIST, userList))
.andExpect(view().name(UserController.VIEW_USER_LIST))
.andExpect(model().attribute(UserController.MODEL_ATTRIBUTE_USER_LIST, hasSize(2)))
.andExpect(model().attribute(UserController.MODEL_ATTRIBUTE_USER_LIST, hasItem(
allOf(
hasProperty("id", is(1L)),
hasProperty("description", is("Lorem ipsum")),
hasProperty("title", is("Foo"))
)
)))
.andExpect(model().attribute(UserController.MODEL_ATTRIBUTE_USER_LIST, hasItem(
allOf(
hasProperty("id", is(2L)),
hasProperty("description", is("Lorem ipsum")),
hasProperty("title", is("Bar"))
)
)));
Run Code Online (Sandbox Code Playgroud) 我有一个场景,我从方法调用中收到一个列表,我想断言该列表包含正确的元素。一种方法是在每个元素中查找一些细节以查看要与哪个预期元素进行比较 - 例如。一个名字。然而,元素还包含一个随机生成的 UUID,我不关心比较。
然后我想一个测试工具可能会来救我。以下面的简化示例为例。
我有一个类狗:
public class Dog {
private String name;
private Integer age;
}
Run Code Online (Sandbox Code Playgroud)
它们包含在一个列表中:
List<Dog> dogs = ... many dogs
Run Code Online (Sandbox Code Playgroud)
现在我想测试该列表是否包含预期的狗,但由于某种原因我不知道某些字段 - 让我们说age. 我已经尝试过使用 assertj 和 hamcrest,但我找不到正确的解决方案,既可以比较两个列表,又可以忽略某些字段。
到目前为止,这就是我所拥有的(使用 hamcrest):
List<Dog> actualDogs = codeUndertest.findDogs(new Owner("Basti"));
List<Dog> expectedDogs = createExpectedListOfDogsWithoutTheAge();
Matcher.assertThat(actualDogs.get(0), Matcher.is(com.shazam.shazamcrest.matcher.Matchers
.sameBeanAs(expectedDogs.(0))
.ignoring("age")
))
Run Code Online (Sandbox Code Playgroud)
这有效,但它只比较 Dog 类的两个对象。我如何比较两个列表中的所有狗?
额外问题:如何在不知道顺序的情况下比较列表,或者我是否只需要断言预期的狗包含在列表中。
说我有这样一个类:
public class Character {
public Character(String name){
this.name = name;
}
private String name;
public String getName() { return name; }
}
Run Code Online (Sandbox Code Playgroud)
后来,一张地图
Map<Character, Integer> characterAges = new HashMap<Character, Integer>();
characterAges.put(new Character("Frodo"), 34);
Run Code Online (Sandbox Code Playgroud)
使用assertj,测试该字符的最佳方法是什么包括"佛罗多"字符?对于这个年龄,我可以这样做:
assertThat(characterAges).hasValue(34);
Run Code Online (Sandbox Code Playgroud)
我知道我能做到:
assertThat(characterAges.keySet())
.extracting("name")
.contains("Frodo");
Run Code Online (Sandbox Code Playgroud)
但后来我失去了流利.我真正想要的是这样的:
assertThat(characterAges)
.hasKey(key.extracting("name").contains("Frodo")
.hasValue(34);
Run Code Online (Sandbox Code Playgroud)
或者甚至更好,以便我可以确保我的密钥和值匹配:
assertThat(characterAges)
.hasEntry(key.extracting("name").contains("Frodo"), 34);
Run Code Online (Sandbox Code Playgroud)
这样的事情可能吗?
给出以下(快速且缺失的)代码:
class Pair{
int x;
int y;
}
List l1 = Arrays.asList(new Match(1,2), new Match(1,3), new Match(2,3));
List l2 = Arrays.asList(new Match(1,2), new Match(1,3), new Match(2,3));
Run Code Online (Sandbox Code Playgroud)
如何比较列表的内容?到目前为止我使用的所有内容都检查对象本身是否相等而不是对象值:
assertThat(l1).isEqualTo(l2);
assertThat(l1).containsAll(l2);
assertThat(l1).containsExactly(values);
assertThat(l1).containsExactlyElementsOf(iterable);
Run Code Online (Sandbox Code Playgroud)
我必须为 Match 类实现 equals() 方法吗?
这可能是正确的方法吗?
for (int i = 0; i < l1.size(); i++){
assertThat(l1.get(i)).usingRecursiveComparison().isEqualTol2.get(i));
}
Run Code Online (Sandbox Code Playgroud) 我正在尝试将我的项目更新到最近发布的Android测试支持库版本1.0.0.但是如果我添加assertj-core依赖关系,Gradle检测的测试任务会因"找不到测试"消息而开始失败.我可以成功地从IDE运行个别测试.
很容易重现这个问题:
assertj-core依赖项../gradlew connectedDebugAndroidTest.Gradle脚本.
android {
defaultConfig {
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
}
dependencies {
implementation 'com.android.support:appcompat-v7:26.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.0'
androidTestImplementation group: "org.assertj", name: "assertj-core", version: "2.8.0"
}
Run Code Online (Sandbox Code Playgroud)
控制台输出.
com.android.builder.testing.ConnectedDevice > No tests found.
[Nexus_4_API_25(AVD) - 7.1.1] FAILED
No tests found. This usually means that your test classes are not in the form that your test runner expects (e.g. don't inherit from TestCase or lack …Run Code Online (Sandbox Code Playgroud) 在停止开发之后我使用FEST-Assert并移动了AssertJ.
最近我被指向谷歌存储库与另一个断言库Truth(http://google.github.io/truth/).
阅读这些例子,我找不到任何开始使用它的优点AssertJ.所以这只是味道的问题.但也许我错过了这一点,是吗?
我想检查String是否包含某个子字符串n次.我知道我能做到:
Assertions.assertThat(myString).contains("xyz");
甚至
Assertions.assertThat(myString).containsOnlyOnce("xyz");
但我怎样才能确保这一次?
我尝试过类似的东西:
Assertions.assertThat(myString).areExactly(n, myString.contains("xyz")); 但遗憾的是这不可编辑.
有任何想法吗?
我有两个班级:
class Outer {
Inner inner = new Inner("value");
}
class Inner {
private final String value;
Inner(String value) {
this.value = value;
}
}
public Optional<Outer> getOptionalValue() {
return Optional.of(new Outer());
}
Run Code Online (Sandbox Code Playgroud)
我的测试:
public void testCLass() {
Assertions.assertThat(getOptionalValue())
.isPresent()
.map(v -> v.inner.value)
.isEqualTo("value");
}
Run Code Online (Sandbox Code Playgroud)
我希望它通过,因为isPresentunwraps 可选,map转换Outer为value最后一种方法,我只是比较字符串。
但它在最后一行失败并显示以下消息:
Expecting:
<Optional[value]>
to be equal to:
<"value">
but was not.
Run Code Online (Sandbox Code Playgroud)
我不知道为什么不展开可选
assertj ×10
java ×7
hamcrest ×2
junit ×2
unit-testing ×2
android ×1
exception ×1
fest-assert ×1
optional ×1
spring-mvc ×1
spring-test ×1
tdd ×1