-1

我是 JUnit 测试的新手,对它的工作原理感到好奇。目前我正在尝试通过单元测试。

测试方法是

@Test
  public void ensure_equals_method_is_properly_coded ()
  {
    assertTrue(employees.get(0).equals(employees.get(2)));
    assertFalse(employees.get(0).equals(employees.get(1)));
    assertFalse(employees.get(0).equals(employees.get(3)));
  }

我有一个 ArrayList 已经填充了其中的值。据我了解,我想编写一个名为 equals() 的方法来让这个测试通过我的任务。我的问题是这种方法将如何找到要测试的方法。我在名为 Persons 的类中创建了一个 equals() 方法,但我不知道在运行测试时它是否被调用。

我的第二个问题是质疑我的 equal() 方法中的逻辑。到目前为止,我有这个。

public boolean equals() {
      if (employees.get(0).equals(employees.get(2))) 

          return true;
    return false;
  }

这应该返回 true,因为第一个测试项断言它是 true。我的逻辑对此是否正确?

只是为了清楚起见,这是我的完整测试课程,一切都已经存在。

public class Tests 
{
  List<Person> employees = new ArrayList<Person>();

  @Before
  public void init ()
  {
    Person anEmployee = new Employee();
    anEmployee.setName("Trevor Page");
    anEmployee.setSex("Male");
    Calendar cal = Calendar.getInstance();
    cal.set(1983, 0, 1);
    anEmployee.setBirthday(cal.getTime());
    ((Employee)anEmployee).setJobTitle("Sr. Software Engineer");
    ((Employee)anEmployee).setOrganization(new Google("Google"));
    employees.add(anEmployee);

    anEmployee = new Employee();
    anEmployee.setName("Jane Doe");
    anEmployee.setSex("Female");
    anEmployee.setBirthday(cal.getTime());
    ((Employee)anEmployee).setJobTitle("Sr. Software Engineer");
    ((Employee)anEmployee).setOrganization(new Google("Google"));
    employees.add(anEmployee);

    anEmployee = new Employee();
    anEmployee.setName("Trevor Page");
    anEmployee.setSex("Male");
    anEmployee.setBirthday(cal.getTime());
    ((Employee)anEmployee).setJobTitle("Sr. Software Engineer");
    ((Employee)anEmployee).setOrganization(new Google("Google"));
    employees.add(anEmployee);

    anEmployee = new Employee();
    anEmployee.setName("Trevor Page");
    anEmployee.setSex("Male");
    anEmployee.setBirthday(cal.getTime());
    ((Employee)anEmployee).setJobTitle("Sr. Software Engineer");
    ((Employee)anEmployee).setOrganization(new Microsoft("Microsoft"));
    employees.add(anEmployee);
  }

  @Test
  public void ensure_toString_method_is_properly_coded()
  {
    String message = "Name: Trevor Page, Sex: Male" +
    "\nJob Title: Sr. Software Engineer, Organization: Google";

    assertThat(employees.get(0).toString(), is(message));
  }

  @Test
  public void ensure_equals_method_is_properly_coded ()
  {
    assertTrue(employees.get(0).equals(employees.get(2)));
    assertFalse(employees.get(0).equals(employees.get(1)));
    assertFalse(employees.get(0).equals(employees.get(3)));
  }

这是我的完整 Persons 类,它是抽象的。我已经有了第一个测试用例。

import java.util.ArrayList;
import java.util.Date;
import java.util.List;


public abstract class Person 
{
  public abstract String getName();
  public abstract String getSex();
  public abstract void setName(String name);
  public abstract void setSex(String sex);
  public abstract void setBirthday(Date birthdate);
  public abstract Date getBirthday();
  public abstract String getJobTitle();
  public abstract String getNameOfOrganization();



  List<Person> employees = new ArrayList<Person>();



  @Override
  public String toString() {  


    return "Name: " + getName() + ", Sex: " + getSex() + "\n" + "Job Title: " + getJobTitle() + ", Organization: " + getNameOfOrganization() ;

     }

}

我有另一个名为 Employee 的类扩展了这个抽象类。

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class Employee extends Person

{

    List<String> employees = new ArrayList<String>();

    @Override
    public String getName() {
        employees.add("Trevor Page");

        return employees.get(0);
    }

    @Override
    public String getSex() {

        employees.add("Male");
        return employees.get(1);

    }

    @Override
    public void setName(String name) {
        // TODO Auto-generated method stub

    }

    @Override
    public void setSex(String sex) {
        // TODO Auto-generated method stub

    }

    @Override
    public void setBirthday(Date birthdate) {
        // TODO Auto-generated method stub

    }

    @Override
    public Date getBirthday() {
        // TODO Auto-generated method stub
        return null;
    }

    public void setJobTitle(String string) {
        // TODO Auto-generated method stub

    }

    public String getJobTitle() {

        employees.add("Sr. Software Engineer");

        return employees.get(2);
    }

    public void setOrganization(Google google) {
        // TODO Auto-generated method stub

    }

    public void setOrganization(Microsoft microsoft) {
        // TODO Auto-generated method stub

    }

    @Override
    public String getNameOfOrganization() {
        employees.add("Google");
        return employees.get(3);
    }

}

我能够通过运气进行第一次测试。我不确定单元测试如何知道测试我的价值观。

4

3 回答 3

0

如果您equals在 person 类中实现,那么您可以断言两个人是否相等。

你上面的内容相当于

Person p1 = employees.get(0);
Person p2 = employees.get(2);
assertTrue(p1.equals(p2));

上面,您直接调用 equals 方法。

但你也可以这样做

assertEquals(p1,p2);

在这种情况下,该Person.equals方法在后台被调用。

方法assertEquals,assertTrueassertFalse其他一些方法可以从org.junit.Assert类中静态导入,有点像:

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertEquals;

或者更简单的形式import static org.junit.Assert.*;

equals 的实现应该简单地验证一个员工是否与另一个员工相等,它不应该像你暗示的那样知道员工列表。

例如

class Person {
   public boolean equals(Object o) {
      if(this==o) {
         return true; 
      }
      if(o instanceof Person) {
         Person other = (Person) o;
         return (this.name == other.name) || (this.name != null && this.name.equals(other.name);
      }
      reurn false;
   }
}

您的测试将包括验证此equals实现是否正确,换句话说,它是否满足类似性、传递性和自反性等属性。请参阅Object.equals方法的 javadocs 以了解更多信息。

于 2013-09-28T02:57:43.840 回答
0

埃德温说的。还:

测试应该调用 equals 并断言返回的布尔值。

这样做可能会令人困惑,因为没有明显的方法来设置员工价值。通常的方法是让employees 字段包可见(没有可访问性修饰符)和Test 类与被测类在同一个包中。

编辑:如果 Person 类是抽象的,请考虑创建一个具体的子类作为允许您对 equals 方法进行单元测试的示例。

于 2013-09-28T03:02:52.590 回答
0

让我首先说明您的equals方法没有在测试中被调用。您实际上是在调用Object.equals(Object o)而不是Person.equals(). 你注意到签名的不同了吗?您的equals方法不带参数,这很不寻常-您应该将等效性与其他东西进行比较。

此外,您的测试设置不合适。您应该建立一个测试数据单元来进行验证。去掉不必要的数据结构;我的意思是你只在一次equals()通话中比较两个对象。

让我们解决这两个问题。

您的equals方法需要覆盖Object.equals. 为此,您需要创建一个具有相同签名的方法。

@Override
public boolean equals(Object other) {
    // What makes two Person instances equivalent?
}

我将把这个实现留给你。考虑到 是 的other情况null

接下来是测试。我更喜欢设置测试的方式是小块。在测试这个逻辑时,有几个方面需要验证:

  • 这两个实例是否具有相同的值?
  • 它们的值是否相同hashCode()?(这是一个约定,如果两个对象相等,则它们的 hashCode 相等。)
  • 如果实例不同,它们是否相等?EG 比较 aPerson和 anInteger应该是...
  • 如果其中一个实例是 ,它们是否相等null

至少,这是四个测试用例。

@Test
public void equals_equivalentInstances() {
    // given
    // two objects that are initialized in the exact same way
    // when + then
    // call the equals() method and assert that the statement is true
}


@Test
public void equals_hashCodeMatches() {
    // given
    // two objects that are initialized in the exact same way
    // when + then
    // call the hashCode() method of both and assert their equivalence
}


@Test
public void equals_handlesDifferentObjectTypes() {
    // given
    // a Person class and some other Object
    // when + then
    // call the equals() method and assert that they are not equal
}

@Test
public void equals_handlesNull() {
    // given
    // two Person classes, one of them initialized to null
    // when + then
    // call the equals() method and assert that they are not equal
}
于 2013-09-28T03:16:22.630 回答