Java 为什么 JUnit 不提供 assertNotEquals 方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1096650/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why doesn't JUnit provide assertNotEquals methods?
提问by Chris B
Does anybody know why JUnit 4 provides assertEquals(foo,bar)
but not assertNotEqual(foo,bar)
methods?
有人知道为什么 JUnit 4 提供assertEquals(foo,bar)
而不是assertNotEqual(foo,bar)
方法吗?
It provides assertNotSame
(corresponding to assertSame
) and assertFalse
(corresponding to assertTrue
), so it seems strange that they didn't bother including assertNotEqual
.
它提供assertNotSame
(对应于assertSame
)和assertFalse
(对应于assertTrue
),所以他们没有打扰包括assertNotEqual
.
By the way, I know that JUnit-addons provides the methods I'm looking for. I'm just asking out of curiosity.
顺便说一下,我知道 JUnit 插件提供了我正在寻找的方法。我只是出于好奇而问。
采纳答案by Joachim Sauer
I'd suggest you use the newer assertThat()
style asserts, which can easily describe all kinds of negations and automatically build a description of what you expected and what you got if the assertion fails:
我建议您使用较新的assertThat()
断言样式,它可以轻松描述各种否定,并自动构建您期望的内容以及断言失败时您得到的内容的描述:
assertThat(objectUnderTest, is(not(someOtherObject)));
assertThat(objectUnderTest, not(someOtherObject));
assertThat(objectUnderTest, not(equalTo(someOtherObject)));
All three options are equivalent, choose the one you find most readable.
所有三个选项都是等效的,请选择您认为最易读的一个。
To use the simple names of the methods (and allow this tense syntax to work), you need these imports:
要使用方法的简单名称(并允许这种紧张的语法起作用),您需要这些导入:
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
回答by Mikko Maunu
I wonder same. The API of Assert is not very symmetric; for testing whether objects are the same, it provides assertSame
and assertNotSame
.
我想知道一样。Assert 的 API 不是很对称;为了测试对象是否相同,它提供assertSame
和assertNotSame
。
Of course, it is not too long to write:
当然,写也不算太长:
assertFalse(foo.equals(bar));
With such an assertion, the only informative part of the output is unfortunately the name of the test method, so descriptive message should be formed separately:
使用这样的断言,不幸的是,输出的唯一信息部分是测试方法的名称,因此应单独形成描述性消息:
String msg = "Expected <" + foo + "> to be unequal to <" + bar +">";
assertFalse(msg, foo.equals(bar));
That is of course so tedious, that it is better to roll your own assertNotEqual
. Luckily in future it will maybe be part of the JUnit: JUnit issue 22
这当然很乏味,最好自己滚动assertNotEqual
。幸运的是,将来它可能会成为 JUnit 的一部分:JUnit 问题 22
回答by Chris Kelly
It's better to use the Hamcrest for negative assertions rather than assertFalse as in the former the test report will show a diff for the assertion failure.
对于否定断言,最好使用 Hamcrest 而不是 assertFalse,因为在前者中,测试报告将显示断言失败的差异。
If you use assertFalse, you just get an assertion failure in the report. i.e. lost information on cause of the failure.
如果您使用assertFalse,您只会在报告中得到一个断言失败。即丢失有关故障原因的信息。
回答by Bernhard Bodenstorfer
I'd argue that the absence of assertNotEqual is indeed an asymmetry and makes JUnit a bit less learnable. Mind that this is a neat case when adding a method would diminish the complexity of the API, at least for me: Symmetry helps ruling the bigger space. My guess is that the reason for the omission may be that there are too few people calling for the method. Yet, I remember a time when even assertFalse did not exist; hence, I have a positive expectation that the method might eventually be added, given that it is not a difficult one; even though I acknowledge that there are numerous workarounds, even elegant ones.
我认为没有 assertNotEqual 确实是一种不对称性,并且使 JUnit 不太容易学习。请注意,当添加方法会降低 API 的复杂性时,这是一个很好的例子,至少对我而言:对称有助于统治更大的空间。我的猜测是,省略的原因可能是调用该方法的人太少了。然而,我记得有一段时间甚至 assertFalse 都不存在;因此,鉴于该方法并不困难,我对最终可能会添加该方法抱有积极的期望;尽管我承认有许多变通方法,甚至是优雅的变通方法。
回答by user903724
I'm coming to this party pretty late but I have found that the form:
我很晚才来参加这个聚会,但我发现表格:
static void assertTrue(java.lang.String message, boolean condition)
can be made to work for most 'not equals' cases.
可以在大多数“不等于”的情况下工作。
int status = doSomething() ; // expected to return 123
assertTrue("doSomething() returned unexpected status", status != 123 ) ;
回答by Stefan Birkner
There is an assertNotEquals
in JUnit 4.11: https://github.com/junit-team/junit/blob/master/doc/ReleaseNotes4.11.md#improvements-to-assert-and-assume
assertNotEquals
JUnit 4.11 中有一个:https: //github.com/junit-team/junit/blob/master/doc/ReleaseNotes4.11.md#improvements-to-assert-and-assume
import static org.junit.Assert.assertNotEquals;
回答by Mark Levison
The obvious reason that people wanted assertNotEquals() was to compare builtins without having to convert them to full blown objects first:
人们想要 assertNotEquals() 的明显原因是比较内置函数,而不必先将它们转换为完整的对象:
Verbose example:
详细示例:
....
assertThat(1, not(equalTo(Integer.valueOf(winningBidderId))));
....
vs.
对比
assertNotEqual(1, winningBidderId);
Sadly since Eclipse doesn't include JUnit 4.11 by default you must be verbose.
遗憾的是,由于 Eclipse 默认不包含 JUnit 4.11,因此您必须详细说明。
Caveat I don't think the '1' needs to be wrapped in an Integer.valueOf() but since I'm newly returned from .NET don't count on my correctness.
警告 我不认为 '1' 需要包含在 Integer.valueOf() 中,但由于我是从 .NET 新回来的,所以不要指望我的正确性。
回答by fatuhoku
Modulo API consistency, why JUnit didn't provide assertNotEquals()
is the same reason why JUnit never provided methods like
Modulo API 一致性,为什么 JUnit 不提供assertNotEquals()
与 JUnit 从未提供类似方法的原因相同
assertStringMatchesTheRegex(regex, str)
vs.assertStringDoesntMatchTheRegex(regex, str)
assertStringBeginsWith(prefix, str)
vs.assertStringDoesntBeginWith(prefix, str)
assertStringMatchesTheRegex(regex, str)
对比assertStringDoesntMatchTheRegex(regex, str)
assertStringBeginsWith(prefix, str)
对比assertStringDoesntBeginWith(prefix, str)
i.e. there's no end to providing a specific assertion methods for the kinds of things you might want in your assertion logic!
即,为您在断言逻辑中可能需要的类型的事物提供特定的断言方法是无止境的!
Far better to provide composable test primitives like equalTo(...)
, is(...)
, not(...)
, regex(...)
and let the programmer piece those together instead for more readability and sanity.
提供可组合的测试原语(如equalTo(...)
、is(...)
、 )要好得多not(...)
,regex(...)
让程序员将它们拼凑在一起,以提高可读性和完整性。
回答by Akshay Vijay Jain
I am working on JUnit in java 8 environment, using jUnit4.12
我正在使用 jUnit4.12 在 java 8 环境中处理 JUnit
for me: compiler was not able to find the method assertNotEquals, even when I usedimport org.junit.Assert;
对我来说:编译器无法找到方法 assertNotEquals,即使我使用import org.junit.Assert;
So I changed assertNotEquals("addb", string);
toAssert.assertNotEquals("addb", string);
所以我改变了assertNotEquals("addb", string);
对Assert.assertNotEquals("addb", string);
So if you are facing problem regarding assertNotEqual
not recognized, then change it to Assert.assertNotEquals(,);
it should solve your problem
因此,如果您遇到有关assertNotEqual
无法识别的问题,请将Assert.assertNotEquals(,);
其更改为它应该可以解决您的问题
回答by davidxxx
I agree totally with the OP point of view. Assert.assertFalse(expected.equals(actual))
is not a natural way to express an inequality.
But I would argue that further than Assert.assertEquals()
, Assert.assertNotEquals()
works but is not user friendly to document what the test actually asserts and to understand/debug as the assertion fails.
So yes JUnit 4.11 and JUnit 5 provides Assert.assertNotEquals()
(Assertions.assertNotEquals()
in JUnit 5) but I really avoid using them.
我完全同意 OP 的观点。 Assert.assertFalse(expected.equals(actual))
不是表达不平等的自然方式。
但我认为,除了Assert.assertEquals()
, Assert.assertNotEquals()
工作但不是用户友好的记录测试实际断言的内容并在断言失败时理解/调试。
所以是的 JUnit 4.11 和 JUnit 5 提供Assert.assertNotEquals()
(Assertions.assertNotEquals()
在 JUnit 5 中)但我真的避免使用它们。
As alternative, to assert the state of an object I general use a matcher API that digs into the object state easily, that document clearly the intention of the assertions and that is very user friendly to understand the cause of the assertion failure.
作为替代方案,我通常使用匹配器 API 来断言对象的状态,该 API 可以轻松深入了解对象状态,该 API 清楚地记录了断言的意图,并且对于理解断言失败的原因非常友好。
Here is an example.
Suppose I have an Animal class which I want to test the createWithNewNameAndAge()
method, a method that creates a new Animal object by changing its name and its age but by keeping its favorite food.
Suppose I use Assert.assertNotEquals()
to assert that the original and the new objects are different.
Here is the Animal class with a flawed implementation of createWithNewNameAndAge()
:
这是一个例子。
假设我有一个 Animal 类,我想测试该createWithNewNameAndAge()
方法,该方法通过更改名称和年龄但保留其最喜欢的食物来创建新的 Animal 对象。
假设我曾经 Assert.assertNotEquals()
断言原始对象和新对象是不同的。
这是一个有缺陷的 Animal 类createWithNewNameAndAge()
:
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+ (or JUnit 5) both as test runner and assertion tool
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);
}
The test fails as expected but the cause provided to the developer is really not helpful. It just says that the values should be different and output the toString()
result invoked on the actual Animal
parameter :
测试按预期失败,但提供给开发人员的原因确实没有帮助。它只是说值应该不同并输出toString()
对实际Animal
参数调用的结果:
java.lang.AssertionError: Values should be different. Actual: Animal
[name=scoubi, age=10, favoriteFood=hay]
at org.junit.Assert.fail(Assert.java:88)
java.lang.AssertionError:值应该不同。实际:动物
[姓名=scoubi,年龄=10,最喜欢的食物=干草]
在 org.junit.Assert.fail(Assert.java:88)
Ok the objects are not equals. But where is the problem ?
Which field is not correctly valued in the tested method ? One ? Two ? All of them ?
To discover it you have to dig in the createWithNewNameAndAge()
implementation/use a debugger while the testing API would be much more friendly if it would make for us the differential between which is expected and which is gotten.
好的,对象不相等。但问题出在哪里?
测试方法中哪个字段的值不正确?一 ?二 ?他们都 ?
要发现它,您必须深入createWithNewNameAndAge()
实现/使用调试器,而测试 API 会更加友好,如果它能让我们区分预期和获得的差异。
JUnit 4.11 as test runner and a test Matcher API as assertion tool
JUnit 4.11 作为测试运行器和一个测试 Matcher API 作为断言工具
Here the same scenario of test but that uses AssertJ (an excellent test matcher API) to make the assertion of the Animal
state: :
这里是相同的测试场景,但使用 AssertJ(一个出色的测试匹配器 API)来进行Animal
状态断言::
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");
}
Of course the test still fails but this time the reason is clearly stated :
当然测试还是失败了,但是这次的原因已经明确了:
java.lang.AssertionError:
Expecting:
<["scoubi", 10, "hay"]>
to contain exactly (and in same order):
<["little scoubi", 1, "hay"]>
but some elements were not found:
<["little scoubi", 1]>
and others were not expected:
<["scoubi", 10]>
at junit5.MyTest.assertListNotEquals_AssertJ(MyTest.java:26)
java.lang.AssertionError:
期待:
<["scoubi", 10, "干草"]>
完全包含(并以相同的顺序):
<["little scoubi", 1, "干草"]>
但未找到某些元素:
<[“小scoubi”,1]>
和其他人没有预料到:
<[“scoubi”,10]>
在 junit5.MyTest.assertListNotEquals_AssertJ(MyTest.java:26)
We can read that for Animal::getName, Animal::getAge, Animal::getFavoriteFood
values of the returned Animal, we expect to have these value :
我们可以读取Animal::getName, Animal::getAge, Animal::getFavoriteFood
返回的 Animal 的值,我们希望有这些值:
"little scoubi", 1, "hay"
but we have had these values :
但我们有这些价值观:
"scoubi", 10, "hay"
So we know where investigate : name
and age
are not correctly valued.
Additionally, the fact of specifying the hay
value in the assertion of Animal::getFavoriteFood()
allows also to more finely assert the returned Animal
. We want that the objects be not the same for some properties but not necessarily for every properties.
So definitely, using a matcher API is much more clear and flexible.
所以我们知道在哪里调查:name
并且age
没有正确估价。此外,hay
在断言中指定值的事实Animal::getFavoriteFood()
也允许更精细地断言返回的Animal
. 我们希望对象对于某些属性不相同,但不一定对于每个属性。
所以肯定的是,使用匹配器 API 更加清晰和灵活。