【发布时间】:2010-10-03 09:38:17
【问题描述】:
我写了我的第一个单元测试,我认为它过于依赖其他模块,我不确定是不是因为:
- 这是一个复杂的测试
- 我实际上已经编写了一个集成测试或
- 我的设计有问题
我首先要说的是,虽然我有大约 4 年的开发经验,但我从来没有学过,也没有教过自动化测试。
我刚刚使用 Hibernate 完成了 DAL 实现的重大更改,我的一位同事建议我为新部分编写单元测试。
主要变化在于切换到每个请求会话模式和更具建设性地使用应用程序事务。
由于上述更改的性质,单元测试从特定请求到达并开始事务的点开始,并且测试在事务结束后结束,并检查事务是否执行了它应该执行的更改。
这一测试涉及初始化以下对象:
- 内存中的 DB- 以便有数据可以处理。
- 初始化公司记录器 - 因为方法取决于它。
- 初始化设计为单例的存储库 - 它是 DAL 的函数入口,但它也存储其他内容,因此它是一个需要创建的大对象。
- 初始化同样是单例的请求处理程序 - 这包含要测试的方法。
我想我实际上已经编写了一个集成测试,因为我需要初始化数据库、Hibernate 和存储库,但我不确定我该如何编写它,否则考虑到测试方法使用所有的情况这些对象的作用,我很想看看事务处理是如何执行的(这是在测试方法上完成的)。
我会很感激所有的 cmets 和想法,如果他们不够清楚,我会很乐意详细说明或澄清问题。
谢谢,
伊泰
附: HibernateSessionFactory 实际上是 Hibernate In Action 书中众所周知的 HibernateUtil,由于历史原因而被错误地命名。
public class AdminMessageRepositoryUpdaterTest {
private static WardId wardId;
private static EmployeeId employeeId;
private static WardId prevWardId;
private static EmployeeId prevEmployeeId;
@Test
public void testHandleEmployeeLoginToWard(){
AgentEmployeesWardsEngine agentEmployeesWardsEngine = new AgentEmployeesWardsEngine();
AgentEngine agentEngine = new AgentEngine();
//Remove all entries from AgentEmployeesWards table
HibernateSessionFactory.beginTransaction();
for (Agent agent : agentEngine.findAll()){
agentEmployeesWardsEngine.removeAgentEntries(agent.getId());
}
HibernateSessionFactory.commitTransaction();//no need to try catch as this is done in a controlled environment
int i=0;
//build expectedSet
Set<AgentEmployeesWards> expectedMappingsToChangeSet = new HashSet<AgentEmployeesWards>();
//Mappings which should have ward updated
expectedMappingsToChangeSet.add(new AgentEmployeesWards(new AgentId(1).getValue(), employeeId.getValue(), prevWardId.getValue(), true, TimestampUtils.getTimestamp(), i++));
expectedMappingsToChangeSet.add(new AgentEmployeesWards(new AgentId(2).getValue(), employeeId.getValue(), prevWardId.getValue(), true, TimestampUtils.getTimestamp(), i++));
//Mappings which should have employee updated
expectedMappingsToChangeSet.add(new AgentEmployeesWards(new AgentId(3).getValue(), prevEmployeeId .getValue(), wardId.getValue(), false, TimestampUtils.getTimestamp(), i++));
expectedMappingsToChangeSet.add(new AgentEmployeesWards(new AgentId(4).getValue(), prevEmployeeId.getValue(), wardId.getValue(), false, TimestampUtils.getTimestamp(), i++));
//Prepare clean data for persistence
Set<AgentEmployeesWards> cleanSet = new HashSet<AgentEmployeesWards>(expectedMappingsToChangeSet);
//Mappings which should NOT have ward updated
cleanSet.add(new AgentEmployeesWards(new AgentId(5).getValue(), employeeId.getValue(), prevWardId.getValue(), false, TimestampUtils.getTimestamp(), i++));
cleanSet.add(new AgentEmployeesWards(new AgentId(6).getValue(), employeeId.getValue(), prevWardId.getValue(), false, TimestampUtils.getTimestamp(), i++));
//Mappings which should NOT have employee updated
cleanSet.add(new AgentEmployeesWards(new AgentId(7).getValue(), prevEmployeeId .getValue(), wardId.getValue(), true, TimestampUtils.getTimestamp(), i++));
cleanSet.add(new AgentEmployeesWards(new AgentId(8).getValue(), prevEmployeeId.getValue(), wardId.getValue(), true, TimestampUtils.getTimestamp(), i++));
HibernateSessionFactory.beginTransaction();
for (AgentEmployeesWards agentEmployeesWards : cleanSet){
agentEmployeesWardsEngine.saveNewAgentEmployeesWardsEntry(agentEmployeesWards);
}
HibernateSessionFactory.commitTransaction();//no need to try catch as this is done in a controlled environment
//Close the session as to neutralize first-level-cache issues
HibernateSessionFactory.closeSession();
//Perform the action so it can be tested
AdminMessageReposityUpdater.getInstance().handleEmployeeLoginToWard(employeeId, wardId, TimestampUtils.getTimestamp());
//Close the session as to neutralize first-level-cache issues
HibernateSessionFactory.closeSession();
//Load actualSet from DAL
Set<AgentEmployeesWards> actualSet = new HashSet<AgentEmployeesWards>(agentEmployeesWardsEngine.findByPrimaryEmployeeId(employeeId));
actualSet.addAll(agentEmployeesWardsEngine.findByPrimaryWardId(wardId));
//Prepare expected
Set<AgentEmployeesWards> expectedSet = new HashSet<AgentEmployeesWards>();
for (AgentEmployeesWards agentEmployeesWards : expectedMappingsToChangeSet){
//We need to copy as the wardId and employeeId are properties which comprise the equals method of the class and so
//they cannot be changed while in a Set
AgentEmployeesWards agentEmployeesWardsCopy = new AgentEmployeesWards(agentEmployeesWards);
if (agentEmployeesWardsCopy.isEmployeePrimary()){
//If this is a employee primary we want it to be updated to the new org-unit id
agentEmployeesWardsCopy.setWardId(wardId.getValue());
} else {
//Otherwise we want it to be updated to the new employee id
agentEmployeesWardsCopy.setEmployeeId(employeeId.getValue());
}
expectedSet.add(agentEmployeesWardsCopy);
}
//Assert between actualSet and expectedSet
// Assert actual database table match expected table
assertEquals(expectedSet, actualSet);
}
@BeforeClass
public static void setUpBeforeClass() throws SQLException,ClassNotFoundException{
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:mem:MyCompany", "sa", "");
ConfigurationDAO configDAO = new ConfigurationDAO();
HibernateSessionFactory.beginTransaction();
configDAO.attachDirty(new Configuration("All","Log", "Level", "Info",null));
configDAO.attachDirty(new Configuration("All","Log", "console", "True",null));
configDAO.attachDirty(new Configuration("All","Log", "File", "False",null));
HibernateSessionFactory.commitTransaction();
Logger log = new Logger();
Server.getInstance().initialize(log);
Repository.getInstance().initialize(log);
AdminMessageReposityUpdater.getInstance().initialize(log);
AdminEngine adminEngine = new AdminEngine();
EmployeeEngine employeeEngine = new EmployeeEngine();
HibernateSessionFactory.beginTransaction();
Ward testWard = new Ward("testWard", 1, "Sales", -1, null);
adminEngine.addWard(testWard);
wardId = new WardId(testWard.getId());
Ward prevWard = new Ward("prevWard", 1, "Finance", -1, null);
adminEngine.addWard(prevWard);
prevWardId = new WardId(prevWard.getId());
Employee testEmployee = new Employee("testEmployee", "test", null, "employee", "f", prevWardId.getValue(), null, false, true);
employeeEngine.setEmployee(testEmployee);
employeeId = new EmployeeId(testEmployee.getId());
Employee prevEmployee = new Employee("prevEmployee", "prev", null, "employee", "f", wardId.getValue(), null, false, true);
employeeEngine.setEmployee(prevEmployee);
prevEmployeeId = new EmployeeId(prevEmployee.getId());
HibernateSessionFactory.commitTransaction();
HibernateSessionFactory.closeSession();
}
@AfterClass
public static void tearDownAfterClass(){
AdminEngine adminEngine = new AdminEngine();
EmployeeEngine employeeEngine = new EmployeeEngine();
HibernateSessionFactory.beginTransaction();
employeeEngine.removeEmployeeById(employeeId);
employeeEngine.removeEmployeeById(prevEmployeeId);
adminEngine.removeWardById(wardId);
adminEngine.removeWardById(prevWardId);
HibernateSessionFactory.commitTransaction();
HibernateSessionFactory.closeSession();
}
}
【问题讨论】:
标签: java unit-testing hibernate integration-testing