有人知道为什么JUnit 4提供assertEquals(foo,bar)方法而不提供assertNotEqual(foo,bar)方法吗?
它提供了assertNotSame(对应于assertSame)和assertFalse(对应于assertTrue),所以它们没有包含assertnotqual似乎很奇怪。
顺便说一下,我知道JUnit-addons提供了我正在寻找的方法。我只是出于好奇才问的。
有人知道为什么JUnit 4提供assertEquals(foo,bar)方法而不提供assertNotEqual(foo,bar)方法吗?
它提供了assertNotSame(对应于assertSame)和assertFalse(对应于assertTrue),所以它们没有包含assertnotqual似乎很奇怪。
顺便说一下,我知道JUnit-addons提供了我正在寻找的方法。我只是出于好奇才问的。
当前回答
人们想要assertNotEquals()的明显原因是比较内置对象,而不必首先将它们转换为完整的对象:
详细的例子:
....
assertThat(1, not(equalTo(Integer.valueOf(winningBidderId))));
....
vs.
assertNotEqual(1, winningBidderId);
不幸的是,由于Eclipse默认情况下不包括JUnit 4.11,您必须详细说明。
注意:我不认为'1'需要包装在Integer.valueOf()中,但由于我刚从。net返回,所以不要指望我的正确性。
其他回答
人们想要assertNotEquals()的明显原因是比较内置对象,而不必首先将它们转换为完整的对象:
详细的例子:
....
assertThat(1, not(equalTo(Integer.valueOf(winningBidderId))));
....
vs.
assertNotEqual(1, winningBidderId);
不幸的是,由于Eclipse默认情况下不包括JUnit 4.11,您必须详细说明。
注意:我不认为'1'需要包装在Integer.valueOf()中,但由于我刚从。net返回,所以不要指望我的正确性。
我在java 8环境下的JUnit工作,使用jUnit4.12
对我来说:编译器无法找到方法assertNotEquals,即使当我使用 进口org.junit.Assert;
所以我改变assertNotEquals("addb",字符串);assertNotEquals(“addb”字符串);
因此,如果您面临关于assertNotEqual不被识别的问题,则将其更改为Assert.assertNotEquals(,);它应该能解决你的问题
我也想知道。Assert的API不是很对称;对于测试对象是否相同,它提供了assertSame和assertNotSame。
当然,写起来也不算太长:
assertFalse(foo.equals(bar));
不幸的是,使用这样的断言,输出中唯一有信息的部分是测试方法的名称,因此应该单独形成描述性消息:
String msg = "Expected <" + foo + "> to be unequal to <" + bar +">";
assertFalse(msg, foo.equals(bar));
这当然是非常乏味的,最好是滚动您自己的assertNotEqual。幸运的是,将来它可能会成为JUnit: JUnit第22期的一部分
我完全同意OP的观点。Assert.assertFalse(expected.equals(actual))不是表达不相等的自然方式。 但我认为,除了Assert.assertEquals()之外,Assert.assertNotEquals()还可以工作,但对于记录测试实际断言的内容以及在断言失败时理解/调试并不友好。 所以是的JUnit 4.11和JUnit 5提供了Assert.assertNotEquals()(断言. assertnotequals()在JUnit 5),但我真的避免使用它们。
作为替代,为了断言一个对象的状态,我通常使用一个匹配器API,它可以很容易地深入对象状态,清楚地记录断言的意图,并且非常便于用户理解断言失败的原因。
这里有一个例子。 假设我有一个Animal类,我想测试createWithNewNameAndAge()方法,这个方法通过改变它的名称和年龄来创建一个新的Animal对象,但保留它最喜欢的食物。 假设我使用assert . assertnotequals()断言原始对象和新对象是不同的。 下面是一个有缺陷的createWithNewNameAndAge()实现的Animal类:
public class Animal {
private String name;
private int age;
private String favoriteFood;
public Animal(String name, int age, String favoriteFood) {
this.name = name;
this.age = age;
this.favoriteFood = favoriteFood;
}
// Flawed implementation : use this.name and this.age to create the
// new Animal instead of using the name and age parameters
public Animal createWithNewNameAndAge(String name, int age) {
return new Animal(this.name, this.age, this.favoriteFood);
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String getFavoriteFood() {
return favoriteFood;
}
@Override
public String toString() {
return "Animal [name=" + name + ", age=" + age + ", favoriteFood=" + favoriteFood + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((favoriteFood == null) ? 0 : favoriteFood.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Animal)) return false;
Animal other = (Animal) obj;
return age == other.age && favoriteFood.equals(other.favoriteFood) &&
name.equals(other.name);
}
}
JUnit 4.11+(或JUnit 5)作为测试运行器和断言工具
@Test
void assertListNotEquals_JUnit_way() {
Animal scoubi = new Animal("scoubi", 10, "hay");
Animal littleScoubi = scoubi.createWithNewNameAndAge("little scoubi", 1);
Assert.assertNotEquals(scoubi, littleScoubi);
}
测试如预期的那样失败了,但是提供给开发人员的原因并没有什么帮助。它只是说值应该是不同的,并输出在实际的Animal参数上调用的toString()结果:
assertionerror:值应该不同。实际:动物 [name=scoubi, age=10, favoriteFood=hay] org.junit.Assert.fail (Assert.java: 88)
两个对象是不相等的。但问题在哪里? 在测试的方法中,哪个字段的值不正确?一个?两个?全部吗? 为了发现它,你必须深入createWithNewNameAndAge()实现/使用调试器,而测试API将更友好,如果它能让我们之间的期望和得到的差异。
JUnit 4.11作为测试运行器,测试Matcher API作为断言工具
这里是相同的测试场景,但使用AssertJ(一个优秀的测试匹配器API)来断言动物状态:
import org.assertj.core.api.Assertions;
@Test
void assertListNotEquals_AssertJ() {
Animal scoubi = new Animal("scoubi", 10, "hay");
Animal littleScoubi = scoubi.createWithNewNameAndAge("little scoubi", 1);
Assertions.assertThat(littleScoubi)
.extracting(Animal::getName, Animal::getAge, Animal::getFavoriteFood)
.containsExactly("little scoubi", 1, "hay");
}
当然,测试仍然失败,但这一次的原因很清楚:
java.lang.AssertionError: 期望: <["scoubi", 10, "hay"]> 精确地包含:精确地包含(以相同的顺序): <["little scoubi", 1, "hay"]> 但有些元素没有被发现: <["little scoubi", 1]> 还有一些是意料之外的: (“scoubi”,10)< > 在junit5.MyTest.assertListNotEquals_AssertJ (MyTest.java: 26)
对于返回的Animal的Animal::getName, Animal::getAge, Animal::getFavoriteFood值,我们期望有这些值:
"little scoubi", 1, "hay"
但是我们有这些价值观:
"scoubi", 10, "hay"
所以我们知道在哪里调查:名字和年龄的值是不正确的。 此外,在断言Animal::getFavoriteFood()中指定干草值的事实也允许更精确地断言返回的Animal。我们希望对象对于某些属性是不同的,而不是每个属性都是相同的。 因此,使用匹配器API无疑更加清晰和灵活。
Modulo API一致性,JUnit不提供assertNotEquals()的原因与JUnit从未提供类似方法的原因相同
assertStringMatchesTheRegex(regex, str) vs. assertStringDoesntMatchTheRegex(regex, str) assertStringBeginsWith(prefix, str) vs. assertStringDoesntBeginWith(prefix, str)
也就是说,为断言逻辑中可能需要的东西提供特定的断言方法是无止境的!
更好的方法是提供可组合的测试原语,如equalTo(…)、is(…)、not(…)、regex(…),并让程序员将这些原语拼凑在一起,以获得更好的可读性和合理性。