Java 断言等于 Junit 中的 2 个列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3236880/
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
Assert equals between 2 Lists in Junit
提问by Kamal
How can I make an equality assertion between lists in a JUnittest case? Equality should be between the content of the list.
如何在JUnit测试用例中的列表之间进行相等断言?列表的内容之间应该相等。
For example:
例如:
List<String> numbers = Arrays.asList("one", "two", "three");
List<String> numbers2 = Arrays.asList("one", "two", "three");
List<String> numbers3 = Arrays.asList("one", "two", "four");
// numbers should be equal to numbers2
//numbers should not be equal to numbers3
回答by Bart Kiers
This is a legacy answer, suitable for JUnit 4.3 and below. The modern version of JUnit includes a built-in readable failure messages in the assertThat method. Prefer other answers on this question, if possible.
这是一个遗留答案,适用于 JUnit 4.3 及以下版本。现代版本的 JUnit 在 assertThat 方法中包含一个内置的可读失败消息。如果可能的话,更喜欢这个问题的其他答案。
List<E> a = resultFromTest();
List<E> expected = Arrays.asList(new E(), new E(), ...);
assertTrue("Expected 'a' and 'expected' to be equal."+
"\n 'a' = "+a+
"\n 'expected' = "+expected,
expected.equals(a));
For the record, as @Paul mentioned in his comment to this answer, two List
s are equal:
作为记录,正如@Paul 在他对这个答案的评论中提到的,两个List
s 是相等的:
if and only if the specified object is also a list, both lists have the same size, and all corresponding pairs of elements in the two lists are equal. (Two elements
e1
ande2
are equal if(e1==null ? e2==null : e1.equals(e2))
.) In other words, two lists are defined to be equal if they contain the same elements in the same order. This definition ensures that the equals method works properly across different implementations of theList
interface.
当且仅当指定的对象也是一个列表,两个列表的大小相同,并且两个列表中所有对应的元素对都相等。(两个元素
e1
,e2
如果,则相等(e1==null ? e2==null : e1.equals(e2))
。)换句话说,如果两个列表以相同的顺序包含相同的元素,则它们被定义为相等。此定义可确保 equals 方法在List
接口的不同实现中正常工作。
See the JavaDocs of the List
interface.
请参阅接口的JavaDocsList
。
回答by djeikyb
I realise this was asked a couple years ago, probably this feature wasn't around then. But now, it's easy to just do this:
我意识到这是几年前被问到的,可能当时还没有这个功能。但是现在,很容易做到这一点:
@Test
public void test_array_pass()
{
List<String> actual = Arrays.asList("fee", "fi", "foe");
List<String> expected = Arrays.asList("fee", "fi", "foe");
assertThat(actual, is(expected));
assertThat(actual, is(not(expected)));
}
If you have a recent version of Junit installed with hamcrest, just add these imports:
如果您安装了带有 hamcrest 的最新版本的 Junit,只需添加这些导入:
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
http://junit.org/junit4/javadoc/latest/org/junit/Assert.html#assertThat(T, org.hamcrest.Matcher)
http://junit.org/junit4/javadoc/latest/org/junit/Assert.html#assertThat(T, org.hamcrest.Matcher)
http://junit.org/junit4/javadoc/latest/org/hamcrest/CoreMatchers.html
http://junit.org/junit4/javadoc/latest/org/hamcrest/CoreMatchers.html
http://junit.org/junit4/javadoc/latest/org/hamcrest/core/Is.html
http://junit.org/junit4/javadoc/latest/org/hamcrest/core/Is.html
回答by Viktor Nordling
If you don't care about the order of the elements, I recommend ListAssert.assertEquals
in junit-addons.
如果你不关心元素的顺序,我推荐ListAssert.assertEquals
在 junit-addons 中。
Link: http://junit-addons.sourceforge.net/
链接:http: //junit-addons.sourceforge.net/
For lazy Maven users:
对于懒惰的 Maven 用户:
<dependency>
<groupId>junit-addons</groupId>
<artifactId>junit-addons</artifactId>
<version>1.4</version>
<scope>test</scope>
</dependency>
回答by Bohemian
Don't reinvent the wheel!
不要重新发明轮子!
There's a Google Code library that does this for you: Hamcrest
有一个 Google 代码库可以为您执行此操作:Hamcrest
[Hamcrest] Provides a library of matcher objects (also known as constraints or predicates) allowing 'match' rules to be defined declaratively, to be used in other frameworks. Typical scenarios include testing frameworks, mocking libraries and UI validation rules.
[Hamcrest] 提供了一个匹配器对象(也称为约束或谓词)库,允许以声明方式定义“匹配”规则,以便在其他框架中使用。典型场景包括测试框架、模拟库和 UI 验证规则。
回答by Arun Pratap Singh
if you don't want to build up an array list , you can try this also
如果你不想建立一个数组列表,你也可以试试这个
@Test
public void test_array_pass()
{
List<String> list = Arrays.asList("fee", "fi", "foe");
Strint listToString = list.toString();
Assert.assertTrue(listToString.contains("[fee, fi, foe]")); // passes
}
回答by Andre Fonseca
Don't transform to string and compare. This is not good for perfomance.
In the junit, inside Corematchers, there's a matcher for this => hasItems
不要转换为字符串并进行比较。这对性能不利。在junit中,在Corematchers内部,有一个匹配器=>hasItems
List<Integer> yourList = Arrays.asList(1,2,3,4)
assertThat(yourList, CoreMatchers.hasItems(1,2,3,4,5));
This is the better way that I know of to check elements in a list.
这是我所知道的检查列表中元素的更好方法。
回答by Ruslan Gafiullin
List<Integer> figureTypes = new ArrayList<Integer>(
Arrays.asList(
1,
2
));
List<Integer> figureTypes2 = new ArrayList<Integer>(
Arrays.asList(
1,
2));
assertTrue(figureTypes .equals(figureTypes2 ));
回答by Ganesa Vijayakumar
I don't this the all the above answers are giving the exact solution for comparing two lists of Objects. Most of above approaches can be helpful in following limit of comparisons only - Size comparison - Reference comparison
我不知道以上所有答案都给出了比较两个对象列表的确切解决方案。上述大多数方法仅有助于遵循比较限制 - 大小比较 - 参考比较
But if we have same sized lists of objects and different data on the objects level then this comparison approaches won't help.
但是如果我们在对象级别上有相同大小的对象列表和不同的数据,那么这种比较方法将无济于事。
I think the following approach will work perfectly with overriding equals and hashcode method on the user-defined object.
我认为以下方法可以完美地覆盖用户定义对象上的 equals 和 hashcode 方法。
I used Xstreamlib for override equals and hashcode but we can override equals and hashcode by out won logics/comparison too.
我使用Xstreamlib 来覆盖 equals 和 hashcode,但我们也可以通过 out won logics/comparison 覆盖 equals 和 hashcode。
Here is the example for your reference
这是供您参考的示例
import com.thoughtworks.xstream.XStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
class TestClass {
private String name;
private String id;
public void setName(String value) {
this.name = value;
}
public String getName() {
return this.name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object o) {
XStream xstream = new XStream();
String oxml = xstream.toXML(o);
String myxml = xstream.toXML(this);
return myxml.equals(oxml);
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
XStream xstream = new XStream();
String myxml = xstream.toXML(this);
return myxml.hashCode();
}
}
public class XstreamCompareTest {
public static void main(String[] args) throws ParseException {
checkObjectEquals();
}
private static void checkObjectEquals() {
List<TestClass> testList1 = new ArrayList<TestClass>();
TestClass tObj1 = new TestClass();
tObj1.setId("test3");
tObj1.setName("testname3");
testList1.add(tObj1);
TestClass tObj2 = new TestClass();
tObj2.setId("test2");
tObj2.setName("testname2");
testList1.add(tObj2);
testList1.sort((TestClass t1, TestClass t2) -> t1.getId().compareTo(t2.getId()));
List<TestClass> testList2 = new ArrayList<TestClass>();
TestClass tObj3 = new TestClass();
tObj3.setId("test3");
tObj3.setName("testname3");
testList2.add(tObj3);
TestClass tObj4 = new TestClass();
tObj4.setId("test2");
tObj4.setName("testname2");
testList2.add(tObj4);
testList2.sort((TestClass t1, TestClass t2) -> t1.getId().compareTo(t2.getId()));
if (isNotMatch(testList1, testList2)) {
System.out.println("The list are not matched");
} else {
System.out.println("The list are matched");
}
}
private static boolean isNotMatch(List<TestClass> clist1, List<TestClass> clist2) {
return clist1.size() != clist2.size() || !clist1.equals(clist2);
}
}
The most important thing is that you can ignore the fields by Annotation (@XStreamOmitField) if you don't want to include any fields on the equal check of Objects. There are many Annotations like this to configure so have a look deep about the annotations of this lib.
最重要的是,如果您不想在 Objects 的平等检查中包含任何字段,您可以通过 Annotation (@XStreamOmitField) 忽略这些字段。有很多这样的注释需要配置,所以深入了解这个库的注释。
I am sure this answer will save your time to identify the correct approach for comparing two lists of objects :). Please comment if you see any issues on this.
我相信这个答案将节省您确定比较两个对象列表的正确方法的时间:)。如果您在这方面看到任何问题,请发表评论。
回答by Dhyan Mohandas
You can use assertEqualsin junit.
您可以在 junit 中使用assertEquals。
import org.junit.Assert;
import org.junit.Test;
@Test
public void test_array_pass()
{
List<String> actual = Arrays.asList("fee", "fi", "foe");
List<String> expected = Arrays.asList("fee", "fi", "foe");
Assert.assertEquals(actual,expected);
}
If the order of elements is different then it will return error.
如果元素的顺序不同,则会返回错误。
If you are asserting a model object list then you should override the equals method in the specific model.
@Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj instanceof ModelName) { ModelName other = (ModelName) obj; return this.getItem().equals(other.getItem()) ; } return false; }
如果您要断言模型对象列表,那么您应该覆盖特定模型中的 equals 方法。
@Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj instanceof ModelName) { ModelName other = (ModelName) obj; return this.getItem().equals(other.getItem()) ; } return false; }
回答by davidxxx
assertEquals(Object, Object)
from JUnit4/JUnit 5 or assertThat(actual, is(expected));
from Hamcrest proposed in the other answers will work only as both equals()
and toString()
are overrided for the classes (and deeply) of the compared objects.
assertEquals(Object, Object)
来自 JUnit4/JUnit 5 或 assertThat(actual, is(expected));
来自其他答案中提出的 Hamcrest 仅适用于两者,equals()
并且toString()
被比较对象的类(和深层)覆盖。
It matters because the equality test in the assertion relies on equals()
and the test failure message relies on toString()
of the compared objects.
For built-in classes such as String
, Integer
and so for ... no problem as these override both equals()
and toString()
. So it is perfectly valid to assert List<String>
or List<Integer>
with assertEquals(Object,Object)
.
And about this matter : you have to override equals()
in a class because it makes sense in terms of object equality, not only to make assertions easier in a test with JUnit.
To make assertions easier you have other ways.
As a good practice I favor assertion/matcher libraries.
这很重要,因为断言中的相等测试equals()
依赖于toString()
比较对象,而测试失败消息依赖于比较对象。
对于内置类,例如String
,Integer
等等... 没问题,因为它们覆盖了equals()
和toString()
。所以断言List<String>
或List<Integer>
with 是完全有效的assertEquals(Object,Object)
。
关于这个问题:您必须equals()
在类中进行覆盖,因为它在对象相等性方面是有意义的,不仅可以在使用 JUnit 的测试中使断言更容易。
为了使断言更容易,您还有其他方法。
作为一个好习惯,我喜欢断言/匹配器库。
Here is a AssertJsolution.
这是一个AssertJ解决方案。
org.assertj.core.api.ListAssert.containsExactly()
is what you need : it verifies that the actual group contains exactly the given values and nothing else, in order as stated in the javadoc.
org.assertj.core.api.ListAssert.containsExactly()
是您所需要的:它验证实际组是否包含给定的值,而没有其他任何内容,如 javadoc 中所述。
Suppose a Foo
class where you add elements and where you can get that.
A unit test of Foo
that asserts that the two lists have the same content could look like :
假设有一个Foo
类,您可以在其中添加元素并且可以在其中获取元素。
一个单元测试Foo
断言两个列表具有相同的内容可能如下所示:
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
@Test
void add() throws Exception {
Foo foo = new Foo();
foo.add("One", "Two", "Three");
Assertions.assertThat(foo.getElements())
.containsExactly("One", "Two", "Three");
}
A AssertJ good point is that declaring a List
as expected is needless : it makes the assertion straighter and the code more readable :
AssertJ 的一个优点List
是不需要按预期声明 a :它使断言更直接,代码更具可读性:
Assertions.assertThat(foo.getElements())
.containsExactly("One", "Two", "Three");
But Assertion/matcher libraries are a must because these will really further.
Suppose now that Foo
doesn't store String
s but Bar
s instances.
That is a very common need.
With AssertJ the assertion is still simple to write. Better you can assert that the list content are equal even if the class of the elements doesn't override equals()/hashCode()
while JUnit way requires that :
但是断言/匹配器库是必须的,因为它们真的会更进一步。
假设现在Foo
不存储String
s 而是Bar
s 实例。
这是一个非常普遍的需求。使用 AssertJ,断言仍然很容易编写。更好的是,您可以断言列表内容是相等的,即使元素的类没有覆盖equals()/hashCode()
而 JUnit 方式要求:
import org.assertj.core.api.Assertions;
import static org.assertj.core.groups.Tuple.tuple;
import org.junit.jupiter.api.Test;
@Test
void add() throws Exception {
Foo foo = new Foo();
foo.add(new Bar(1, "One"), new Bar(2, "Two"), new Bar(3, "Three"));
Assertions.assertThat(foo.getElements())
.extracting(Bar::getId, Bar::getName)
.containsExactly(tuple(1, "One"),
tuple(2, "Two"),
tuple(3, "Three"));
}