排序列表上的 AssertEquals 总是返回 false
AssertEquals on sorted lists always returning false
我正在尝试编写一个单元测试来测试两个列表的排序。我所拥有的是调用自定义排序比较器,然后将原始列表与排序后的列表进行比较。然后我使用 assertEquals 来测试排序列表和原始列表是否匹配。
假设我有一个简单的模型……患者。
患者有两个字段...姓名和年龄。
List<Patient> unOrdered = new ArrayList<Patient>();
List<Patient> ordered = new ArrayList<Patient>();
我用同样的三个病人填满这两个,然后正确地订购订购的那个。
ordered.add(new Patient("Chris Bacon", "45"));
ordered.add(new Patient("Charles Steak", "82"));
ordered.add(new Patient("Matt Pork", "32"));
那我把订的填上,按年龄从大到小排序。
unOrdered.add(new Patient("Matt Pork", "32"));
unOrdered.add(new Patient("Chris Bacon", "45"));
unOrdered.add(new Patient("Charles Steak", "82"));
然后,在我的单元测试中,我写了一个 Collections.sort 和一个自定义比较器来按年龄升序对无序列表进行排序。我在测试期间(对我而言)将该列表打印到控制台,然后执行...
assertEquals(ordered, unOrdered);
控制台以相同的顺序打印出这些列表,但 assertEquals returns 为假。我什至尝试过以相同的顺序创建两个完全相同的列表并尝试使用 assertEquals,但它仍然 returns false.
我不是 Java 专家,但根据我在网上阅读的内容和文档 assertEquals 不仅检查列表中对象的相等性,还检查对象的顺序。那么......为什么它总是返回错误?是 assertEquals 无法处理更复杂的对象还是我做错了什么?
为了使两个列表相等,一个列表的每个元素都必须与另一个列表的相应元素进行比较,因此此测试完全依赖于 Patient
equals 方法的实现。
请看这个演示代码,它可以运行没有错误。和你的对比一下,找出问题所在。
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.junit.Test;
class Patient {
private String name;
private String age;
/**
* Constructor
* @param name
* @param age
*/
public Patient(String name, String age) {
super();
this.name = name;
this.age = age;
}
/**
* This is the override of super method.
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((age == null) ? 0 : age.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
/**
* This is the override of super method.
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Patient other = (Patient) obj;
if (age == null) {
if (other.age != null)
return false;
} else if (!age.equals(other.age))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the age
*/
public String getAge() {
return age;
}
/**
* @param age the age to set
*/
public void setAge(String age) {
this.age = age;
}
}
/**
* Unit test for simple App.
*/
public class AppTest {
/**
* Rigourous Test :-)
*/
@Test
public void testApp() {
List<Patient> unOrdered = new ArrayList<Patient>();
List<Patient> ordered = new ArrayList<Patient>();
ordered.add(new Patient("Charles Steak", "82"));
ordered.add(new Patient("Chris Bacon", "45"));
ordered.add(new Patient("Matt Pork", "32"));
unOrdered.add(new Patient("Matt Pork", "32"));
unOrdered.add(new Patient("Chris Bacon", "45"));
unOrdered.add(new Patient("Charles Steak", "82"));
Collections.sort(unOrdered, new Comparator<Patient>(){
/**
* This method is just for demo. Not well defined.
*
* @param o1
* @param o2
* @return
*/
@Override
public int compare(Patient o1, Patient o2) {
return o1.getName().compareTo(o2.getName());
}});
assertEquals(ordered, unOrdered);
}
}
当你比较列表时,它基本上取决于 List
它将如何执行。但是,对于大多数列表,您只需迭代所有元素并使用 equals
方法逐一比较元素。因此,在您的情况下,您需要为 Patient
class 提供 equals
方法。并且,一如既往 - 还提供 hashCode
实施(这被认为是最佳实践)。
类似这样的东西(如果你使用的是 Java 8):
public class Patient {
private final String age;
private final String name;
public Patient(final String name, final String age) {
this.name = name;
this.age = age;
}
public String getAge() {
return age;
}
public String getName() {
return name;
}
@Override
public boolean equals(Object o) {
if (o instanceof Patient) {
Patient other = (Patient) o;
return Objects.equals(getName(), other.getName()) && Objects.equals(getAge(), other.getAge());
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(getName(), getAge());
}
}
附带说明一下,我不建议使用 String
作为 age
因为。考虑对年龄 "2"
或 "10"
进行排序。字符串值 "10"
出现在 "2"
之前,这可能不是本意。
此外,要对 Patient
对象进行排序,您可以使用一些漂亮的 Java 8 功能,例如:
// An unordered list of all patients
List<Patient> allPatients = Arrays.asList(
new Patient("Matt Pork", "32"),
new Patient("Chris Bacon", "45"),
new Patient("Charles Steak", "82")
);
// Sort by name
List<Patient> sortedByName = allPatients.stream()
.sorted(Comparator.comparing(Patient::getName))
.collect(Collectors.toList());
// Sort by age
List<Patient> sortedByAge = allPatients.stream()
.sorted(Comparator.comparing(Patient::getAge))
.collect(Collectors.toList());
请注意,您实际上并未对基础 List
进行排序,您只需创建一个具有正确顺序的新 List
。
您可以在 this excellent tutorial 中阅读有关 Java 8 Streams 的更多信息,其中包括排序、过滤等。
我正在尝试编写一个单元测试来测试两个列表的排序。我所拥有的是调用自定义排序比较器,然后将原始列表与排序后的列表进行比较。然后我使用 assertEquals 来测试排序列表和原始列表是否匹配。
假设我有一个简单的模型……患者。
患者有两个字段...姓名和年龄。
List<Patient> unOrdered = new ArrayList<Patient>();
List<Patient> ordered = new ArrayList<Patient>();
我用同样的三个病人填满这两个,然后正确地订购订购的那个。
ordered.add(new Patient("Chris Bacon", "45"));
ordered.add(new Patient("Charles Steak", "82"));
ordered.add(new Patient("Matt Pork", "32"));
那我把订的填上,按年龄从大到小排序。
unOrdered.add(new Patient("Matt Pork", "32"));
unOrdered.add(new Patient("Chris Bacon", "45"));
unOrdered.add(new Patient("Charles Steak", "82"));
然后,在我的单元测试中,我写了一个 Collections.sort 和一个自定义比较器来按年龄升序对无序列表进行排序。我在测试期间(对我而言)将该列表打印到控制台,然后执行...
assertEquals(ordered, unOrdered);
控制台以相同的顺序打印出这些列表,但 assertEquals returns 为假。我什至尝试过以相同的顺序创建两个完全相同的列表并尝试使用 assertEquals,但它仍然 returns false.
我不是 Java 专家,但根据我在网上阅读的内容和文档 assertEquals 不仅检查列表中对象的相等性,还检查对象的顺序。那么......为什么它总是返回错误?是 assertEquals 无法处理更复杂的对象还是我做错了什么?
为了使两个列表相等,一个列表的每个元素都必须与另一个列表的相应元素进行比较,因此此测试完全依赖于 Patient
equals 方法的实现。
请看这个演示代码,它可以运行没有错误。和你的对比一下,找出问题所在。
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.junit.Test;
class Patient {
private String name;
private String age;
/**
* Constructor
* @param name
* @param age
*/
public Patient(String name, String age) {
super();
this.name = name;
this.age = age;
}
/**
* This is the override of super method.
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((age == null) ? 0 : age.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
/**
* This is the override of super method.
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Patient other = (Patient) obj;
if (age == null) {
if (other.age != null)
return false;
} else if (!age.equals(other.age))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the age
*/
public String getAge() {
return age;
}
/**
* @param age the age to set
*/
public void setAge(String age) {
this.age = age;
}
}
/**
* Unit test for simple App.
*/
public class AppTest {
/**
* Rigourous Test :-)
*/
@Test
public void testApp() {
List<Patient> unOrdered = new ArrayList<Patient>();
List<Patient> ordered = new ArrayList<Patient>();
ordered.add(new Patient("Charles Steak", "82"));
ordered.add(new Patient("Chris Bacon", "45"));
ordered.add(new Patient("Matt Pork", "32"));
unOrdered.add(new Patient("Matt Pork", "32"));
unOrdered.add(new Patient("Chris Bacon", "45"));
unOrdered.add(new Patient("Charles Steak", "82"));
Collections.sort(unOrdered, new Comparator<Patient>(){
/**
* This method is just for demo. Not well defined.
*
* @param o1
* @param o2
* @return
*/
@Override
public int compare(Patient o1, Patient o2) {
return o1.getName().compareTo(o2.getName());
}});
assertEquals(ordered, unOrdered);
}
}
当你比较列表时,它基本上取决于 List
它将如何执行。但是,对于大多数列表,您只需迭代所有元素并使用 equals
方法逐一比较元素。因此,在您的情况下,您需要为 Patient
class 提供 equals
方法。并且,一如既往 - 还提供 hashCode
实施(这被认为是最佳实践)。
类似这样的东西(如果你使用的是 Java 8):
public class Patient {
private final String age;
private final String name;
public Patient(final String name, final String age) {
this.name = name;
this.age = age;
}
public String getAge() {
return age;
}
public String getName() {
return name;
}
@Override
public boolean equals(Object o) {
if (o instanceof Patient) {
Patient other = (Patient) o;
return Objects.equals(getName(), other.getName()) && Objects.equals(getAge(), other.getAge());
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(getName(), getAge());
}
}
附带说明一下,我不建议使用 String
作为 age
因为。考虑对年龄 "2"
或 "10"
进行排序。字符串值 "10"
出现在 "2"
之前,这可能不是本意。
此外,要对 Patient
对象进行排序,您可以使用一些漂亮的 Java 8 功能,例如:
// An unordered list of all patients
List<Patient> allPatients = Arrays.asList(
new Patient("Matt Pork", "32"),
new Patient("Chris Bacon", "45"),
new Patient("Charles Steak", "82")
);
// Sort by name
List<Patient> sortedByName = allPatients.stream()
.sorted(Comparator.comparing(Patient::getName))
.collect(Collectors.toList());
// Sort by age
List<Patient> sortedByAge = allPatients.stream()
.sorted(Comparator.comparing(Patient::getAge))
.collect(Collectors.toList());
请注意,您实际上并未对基础 List
进行排序,您只需创建一个具有正确顺序的新 List
。
您可以在 this excellent tutorial 中阅读有关 Java 8 Streams 的更多信息,其中包括排序、过滤等。