【问题标题】:AssertEquals on sorted lists always returning false排序列表上的 AssertEquals 总是返回 false
【发布时间】:2015-01-28 03:21:19
【问题描述】:

我正在尝试编写一个单元测试来测试两个列表的排序。我所拥有的是调用自定义排序比较器,然后将原始列表与排序列表进行比较。然后我使用 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,以按年龄升序对 unOrdered 列表进行排序。我在测试期间(对我而言)将该列表打印到控制台,然后执行...

assertEquals(ordered, unOrdered);

控制台以相同的顺序打印这些列表,但 assertEquals 返回 false。我什至尝试以相同的顺序创建两个完全相同的列表并尝试 assertEquals ,它仍然返回 false。

我不是 Java 专家,但根据我在网上阅读的内容和文档 assertEquals 不仅检查列表中对象的相等性,还检查对象的顺序。那么......为什么它总是返回假?是 assertEquals 无法处理更复杂的对象还是我做错了什么?

【问题讨论】:

  • Patientequals 方法吗?如果不是,它将使用默认的基于身份的相等性,并且您将不同的实例放在两个列表中。
  • @PatriciaShanahan 我确实有一个 equals 方法,但我没想过在那里检查。当然,问题就在那里。谢谢。

标签: java unit-testing junit


【解决方案1】:

要使两个列表相等,一个列表的每个元素都必须与另一个列表的对应元素比较相等,因此该测试完全依赖于Patient equals 方法的实现。

【讨论】:

    【解决方案2】:

    比较列表时,基本上取决于List 的执行方式。但是,对于大多数列表,您只需迭代所有元素并使用equals 方法一一比较元素。因此,在您的情况下,您需要为 Patient 类提供 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 的更多信息,其中包括排序、过滤等。

    【讨论】:

      【解决方案3】:

      请看这个演示代码,它可以正常运行。和你的对比一下,找出问题所在。

      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);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-05-19
        • 2013-01-27
        • 2022-01-16
        • 2016-07-20
        • 2021-11-05
        • 2018-11-05
        • 2019-05-06
        相关资源
        最近更新 更多