在我的公司,我们正在为代码处理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)
答案 0 :(得分:0)
1)为可测试性目的引入接口可能对最终类有意义,因为您无法以传统方式模拟它们。
这真的不是你的背景。
2)将接口放在数据模型类的前面有哪些优势?您将无法多次访问/设置数据方法。
因此,JPA / Hibernate实体的接口引入零增值
它使已经可测试的代码的应用程序代码变得复杂。
在示例中为灯具创建匿名类会使测试代码更加复杂。