在单元测试中使用hibernate实体是不好的做法,我应该嘲笑它们吗?

时间:2017-05-13 12:52:57

标签: java hibernate junit

在我的公司,我们正在为代码处理Hibernate实体编写单元测试,我们想在以下两者之间做出决定:

“简单”版本 - 在单元测试中使用实体对象。

“解耦”版本 - 让实体实现接口,并在单元测试中使用模拟对象。

请告诉我你是否看到使用“去耦”版本的任何实际好处,因为否则,简单性会赢。

原始代码包括员工实体:

@Entity
@Table(name="employees")
public class Employee {
  // private members ...    

  @Column(name="id")
  public int getId() {
     return id;
  }

  @Column(name="name")
  public String getName() {
    return name;
  }

  @ManyToOne(cascade=CascadeType.ALL)
  public Department getDepartment() {
    return department;
  }

  // Setter methods ...
}

部门实体:

@Entity
@Table(name="departments")
public class Department {
  // private members ...    

  @Column(name="id")
  public int getId() {
     return id;
  }

  @Column(name="name")
  public String getName() {
    return name;
  }

  @OneToMany(cascade=CascadeType.ALL)
  public Set<Employees> getEmployees() {
    return employees;
  }

  // Setter methods ...
}

“简单”版本的单元测试代码:

@Test
public void twoEmployeesWithSameDepartmentAreCoworkers() {

  Department finance = new Department();
  finance.setId(30);
  finance.setName("Finance");

  Employee smith = new Employee();
  smith.setId(101);
  smith.setName("John Smith"); 
  smith.setDepartment(finance);

  Employee banks = new Employee();
  smith.setId(102);
  smith.setName("Merry Banks"); 
  smith.setDepartment(finance);

  boolean expectedResult = true;
  boolean result = employeeService.areEmployeesCoworkers(smith, banks);
  assertEquals(expectedResult, result);
}

在“解耦”版本中,应进行一些更改,实体如下所示:

两个新界面:

public interace IEmployee {
  public int getId();
  public String getName();
  public IDepartment getIDepartment();
}

public interace IDepartment {
  public int getId();
  public String getName();
  public Set<IEmployee> getIEmployees();
}

实体员工现在实施IEmployee:

public class Employee implements IEmployee {
  // private members ... 

  @Column(name="id")
  @Override
  public int getId() {
     return id;
  }

  @Column(name="name")
  @Override
  public String getName() {
    return name;
  }

  @ManyToOne(cascade=CascadeType.ALL)
  public Department getDepartment() {
    return department;
  }

  @Override
  public IDepartment getIDepartment() {
    return getDepartment();
  }

  // Setter methods ...
}

实体部门现在实施IDepartment:

public class Department implements IDepartment {
  // private members ... 

  @Column(name="id")
  @Override
  public int getId() {
     return id;
  }

  @Column(name="name")
  @Override
  public String getName() {
    return name;
  }

  @OneToMany(cascade=CascadeType.ALL)
  public Set<Employees> getEmployees() {
    return employees;
  }

  @Override
  public Set<IEmployees> getIEmployees() {
    Set<IEmployees> iemployees = new HashSet<IEmployees>();
    iemployees.addAll(getEmployees());
    return iemployees;
  }

  // Setter methods ...
}

“松散耦合”版本的单元测试代码:

@Test
public void twoEmployeesWithSameDepartmentAreCoworkers() {

  Set<IEmployee> financeMockedEmployees = new HashSet<IEmployee>();

  IDepartment mockedFinance = new IDepartment() {
    public int getId() {
      return 30;
    }
    public String getName() {
      return "Finance";
    }
    public Set<IEmployee> getIEmployees() {
      return financeMockedEmployees;
    }
  };

  IEmployee mockedSmith = new IEmployee() {
    public int getId() {
      return 101;
    }

    public String getName() {
      return "John Smith";
    }

    public IDepartment getIDepartment() {
      return mockedFinance;
    }
  };

  IEmployee mockedBanks = new IEmployee() {
    public int getId() {
      return 102;
    }

    public String getName() {
      return "Merry Banks";
    }

    public IDepartment getIDepartment() {
      return mockedFinance;
    }
  };

  financeMockedEmployees.add(mockedSmith);
  financeMockedEmployees.add(mockedBanks);

  boolean expectedResult = true;
  boolean result = employeeService.areEmployeesCoworkers(mockedSmith, mockedBanks);
  assertEquals(expectedResult, result);
}

请注意 areEmployeesCoworkers 方法是第一个:

public boolean areEmployeesCoworkers(Employee emp1, Employee emp2)

现在是:

public boolean areEmployeesCoworkers(IEmployee emp1, IEmployee emp2)

1 个答案:

答案 0 :(得分:0)

1)为可测试性目的引入接口可能对最终类有意义,因为您无法以传统方式模拟它们。
这真的不是你的背景。

2)将接口放在数据模型类的前面有哪些优势?您将无法多次访问/设置数据方法。

因此,JPA / Hibernate实体的接口引入零增值 它使已经可测试的代码的应用程序代码变得复杂。

在示例中为灯具创建匿名类会使测试代码更加复杂。