Java 为什么';JUnit是否提供assertNotEquals方法?
有人知道为什么JUnit4提供Java 为什么';JUnit是否提供assertNotEquals方法?,java,junit,assert,Java,Junit,Assert,有人知道为什么JUnit4提供assertEquals(foo,bar)而不提供assertNotEqual(foo,bar)方法吗 它提供了assertNotSame(对应于assertSame)和assertFalse(对应于assertTrue),所以它们不费事包括assertNotEqual,这似乎很奇怪 顺便说一下,我知道JUnit插件提供了我正在寻找的方法。我只是出于好奇才这么问。我也不知道。Assert的API不是很对称;为了测试对象是否相同,它提供了assertSame和asse
assertEquals(foo,bar)
而不提供assertNotEqual(foo,bar)
方法吗
它提供了assertNotSame
(对应于assertSame
)和assertFalse
(对应于assertTrue
),所以它们不费事包括assertNotEqual
,这似乎很奇怪
顺便说一下,我知道JUnit插件提供了我正在寻找的方法。我只是出于好奇才这么问。我也不知道。Assert的API不是很对称;为了测试对象是否相同,它提供了
assertSame
和assertNotSame
当然,写这篇文章不会太长:
assertFalse(foo.equals(bar));
不幸的是,使用这种断言,输出的唯一信息部分是测试方法的名称,因此应单独形成描述性消息:
String msg = "Expected <" + foo + "> to be unequal to <" + bar +">";
assertFalse(msg, foo.equals(bar));
String msg=“预期不等于”;
assertFalse(msg,foo.equals(bar));
这当然是非常乏味的,因此最好使用自己的
assertNotEqual
。幸运的是,将来它可能会成为JUnit的一部分:我建议您使用较新样式的断言,它可以轻松地描述各种否定,并自动构建一个描述,描述您期望的内容以及在断言失败时得到的内容:
assertThat(objectUnderTest, is(not(someOtherObject)));
assertThat(objectUnderTest, not(someOtherObject));
assertThat(objectUnderTest, not(equalTo(someOtherObject)));
这三个选项都是等效的,请选择您认为最可读的选项 要使用方法的简单名称(并允许这种时态语法工作),您需要以下导入:
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
最好将Hamcrest用于否定断言,而不是assertFalse,因为在前者中,测试报告将显示断言失败的差异
如果使用assertFalse,则报告中只会出现断言失败。i、 e.关于失败原因的信息丢失。我认为缺少assertNotEqual确实是一种不对称现象,使JUnit变得不那么容易学习。请注意,当添加一个方法将降低API的复杂性时,这是一个很好的例子,至少对我来说是这样:对称性有助于控制更大的空间。
我的猜测是,遗漏的原因可能是呼吁采用这种方法的人太少了。然而,我记得有一段时间,甚至assertFalse都不存在;因此,我有一个积极的期望,即该方法最终可能会被添加,因为它不是一个困难的方法;尽管我承认有很多变通方法,甚至是优雅的。我来参加这个聚会的时间很晚,但我发现:
static void assertTrue(java.lang.String message, boolean condition)
可用于大多数“不平等”情况
int status = doSomething() ; // expected to return 123
assertTrue("doSomething() returned unexpected status", status != 123 ) ;
JUnit4.11中有一个
assertNotEquals
:
人们想要assertNotEquals()的明显原因是比较内置对象,而不必首先将它们转换为完整的对象: 详细示例:
....
assertThat(1, not(equalTo(Integer.valueOf(winningBidderId))));
....
vs
不幸的是,由于Eclipse默认不包括JUnit4.11,所以您必须非常详细
注意:我认为不需要将“1”包装为整数.valueOf(),但由于我是从.NET新返回的,所以不要指望我的正确性。模API一致性,JUnit为什么不提供
assertNotEquals()
也是JUnit从未提供类似的方法的原因
vs.assertstringmatchesteregex(regex,str)
assertStringDoesntMatchTheRegex(regex,str)
vs.assertStringBeginsWith(前缀,str)
assertstringdoesntbeginwhith(前缀,str)
更好的方法是提供可组合的测试原语,如
equalTo(…)
,is(…)
,not(…)
,regex(…)
,让程序员将这些原语组合在一起,以提高可读性和可靠性。我正在使用jUnit4.12在java 8环境中开发JUnit
对我来说:编译器无法找到方法assertNotEquals,即使在我使用import org.junit.Assert代码>
因此,我更改了assertNotEquals(“addb”,string)代码>
到
Assert.assertNotEquals(“addb”,字符串)代码>
所以,如果您面临有关assertNotEqual
无法识别的问题,那么将其更改为Assert.assertNotEquals(,)代码>它应该能解决你的问题我完全同意OP的观点Assert.assertFalse(预期的.equals(实际的))
不是表示不等式的自然方式。
但是我认为,除了Assert.assertEquals()
,Assert.assertNotEquals()
可以工作,但是对于记录测试实际断言的内容以及在断言失败时理解/调试,它不是用户友好的。
是的,JUnit4.11和JUnit5提供了Assert.assertNotEquals()
(JUnit5中的Assertions.assertNotEquals()
),但我确实避免使用它们
作为替代方案,为了断言对象的状态,我通常使用一个MatcherAPI,该API可以轻松地挖掘对象状态,清楚地记录断言的意图,并且非常方便用户理解断言失败的原因
下面是一个例子。
假设我有一个动物类,我想测试createWithNewNameAndAge()
方法,该方法通过更改名称和年龄但保留其喜爱的食物来创建新的动物对象。
假设我使用Assert.assertNotEquals()
断言原始对象和新对象是不同的。
下面是Animal类,其createWithNewNameAndAge()的实现存在缺陷。
:
JUnit4.11+(或JUnit5)作为测试运行程序和断言工具
@Test
void assertListNotEquals_JUnit_way() {
Animal scoubi = new Animal("scoubi", 10, "hay");
Animal littleScoubi = scoubi.createWithNewNameAndAge("little scoubi", 1);
Assert.assertNotEquals(scoubi, littleScoubi);
}
测试按预期失败,但提供给开发人员的原因确实没有帮助。它只是说这些值应该不同,并输出在实际的动物上调用的toString()
结果
assertNotEqual(1, winningBidderId);
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);
}
}
@Test
void assertListNotEquals_JUnit_way() {
Animal scoubi = new Animal("scoubi", 10, "hay");
Animal littleScoubi = scoubi.createWithNewNameAndAge("little scoubi", 1);
Assert.assertNotEquals(scoubi, littleScoubi);
}
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");
}
"little scoubi", 1, "hay"
"scoubi", 10, "hay"
assertTrue(obj1.equals(obj2));
assertFalse(obj1.equals(obj2));