单元测试,是一种直接面向生产代码的测试,是一种白盒测试。
以前也写过那种超级简单的,就是依赖DB的基于dao或者service层接口的测试,简单的加载一些spring配置,然后开测。说实话,这样做有好处,最大的好处就是我知道这个接口可以运行了。仅此而已。
我对单元测试一直抱有抵触心态,可能跟周围同事的环境有关系,我没有发现说单元测试多么多么好的,反而发现有很多抱怨的,单元测试要做好难啊、单元测试费尽不讨好阿、单元测试太耗费时间啊。。。
我觉得单元测试最主要的是保证开发人员所写代码的可运行性就足够了,边界、路径、业务逻辑...大可以不写,那后面这些由什么保证呢?集成测试,我觉得集成测试完全可以覆盖这些。欢迎大家拍砖。
我们的项目曾经试验性的使用EasyMock结合junit写了几个单元测试,好坏我评价不了,大牛自己说太累了,哇,代码好多,一堆mock对象,而且还要对流程和代码极其熟悉。当然了,我们的大牛这几个单元测试,主要测得是业务逻辑的准确性,所以会导致乍一看,给人门槛很高的感觉。
先来看一个测试service的某种case的例子吧:
public class TestRegistrationService extends TestCase {
ILogInfoDAO logInfoDAO = createMock(ILogInfoDAO.class);
DaoManager daoMgr = createMock(DaoManager.class);
public void initDaoManager(){
reset();
expect(daoMgr.getDao(ILogInfoDAO.class)).andReturn(logInfoDAO).anyTimes();
daoMgr.startTransaction();
daoMgr.commitTransaction();
daoMgr.endTransaction();
DaoConfig dao=DaoConfig.getInstance();
dao.setDaoManager(daoMgr);
}
public void testAutoRegistrationServiceInvalidMSISDN() throws Exception{
initDaoManager();
logInfoDAO.addSelfRegisterHistory((RegistrationLogInfo) anyObject());
expectLastCall().andDelegateTo(new LogInfoDAOImpl(){
@Override
public void addSelfRegisterHistory(RegistrationLogInfo logInfo)
throws Exception {
String desp=logInfo.getDescription();
assertEquals(Constants.REGLOGINFO_INVALID_MSISDN_FORMAT, desp);
}
});
replay(daoMgr,deviceDAO,subscriberDAO,logInfoDAO,otherDAO,modelDAO,stateManagerDAO);
RegistrationService service=new RegistrationService(1);
try{
service.autoRegistrationService("131612213", "IMEI:004401020858052", "NOKIA", "6670", "R533", "1", "1");
}catch(DMCareException e){
return;
}
assert(false);
verify(daoMgr,deviceDAO,subscriberDAO,logInfoDAO,otherDAO,modelDAO,stateManagerDAO);
}
}
这还只是一个service中的一种case,如果要覆盖全了,比真正的生产代码量不知道要大多少。
当然这样做也有好处,不需要容器和db依赖。
所以单元测试,到底是测什么?或者这么说,对于一个已经存在系统进行改造,单元测试该怎么写??