记得我以前写过一个文章是有关于4层web结构单元测试的,今天打算对TDD的环境问题重新讨论一下。
我当时的4层结构的单元测试时间上是从DAO到Service到Action再到JSP一种渐进测试,但是的想法是,先测DAO,那么Service对DAO的调用就有保证了,测试了Service,那么action调用service就有保证了。。。这样一层一层下来,我每层测试的目标也就达到了。这里其实我用了一个技巧,就是通过测试的顺序,来逐渐的构建了每层测试所需的外部环境。当然从这个角度来看,我当时使用的方法更贴近于集成测试了。
一般做TDD的时候最大的问题就是如何处理外部环境,这一般包括本身业务逻辑环境和技术框架环境。
在当前这个新项目中,我首先尝试对一个具体渲染器的测试方式就是用mock,这里用的是比较好用的easyMock。开始的时候觉得mock的方法很好用,但是当我发现我的待测方法中有多个需要mock的对象时(a.getX();b.getY();c.getZ())或者一个mock对象要通过多次级联获取时(如 a.getB().getC().getD().getE())就会发现mock的代价让你高到很不原意mock的地步。
而且当我们的框架却制造了一个让我无法逾越的障碍,就是我们对于manager(DAO)的调用都是用一个类的静态方法封装管理(比较奇怪为什么不用spring来进行管理呢)。这样静态方法就没法mock了,于是乎,要想测试就要采用build的方法了,就是你可以在你的testCase中事先通过已经实现好的DAO方法把需要使用到的业务对象真实的build出来,这样你就可以知道你的被测方法中通过dao调用到的数据究竟是什么了,于是就可以对你期望获得的结果和经过实际方法得到的结果进行对比验证了。
看起来好像也是比较方便,但是实际上当你待测对象的业务模型,依赖于3-4级以上的相关模型时,你就会感觉到,这样build是一个代价非常高的事情。这种代价通常会让开发者丧失对TDD的兴趣了。
我发现其实在测试的时候我更加关注的是业务数据的build,而系统架构通常是服务于业务的。所以我就开始考虑,能否有个方法构建出最基本需要的业务模型数据呢。查阅了一些网上工具,发现没有能够满足我当前需求(kodo做持久层,还有我们自己研发的知识引擎),于是就自己简单做了一个InitialTestObject,想法很简单就是通过一个xml文件然后根据已知的业务模型结构定义好数据,然后根据固定的规则初始化好业务数据,并且存放到一个map中去(方法比较简单我就不列出源码了),然后再使用时把初始化放到setUp中去,这样在测试的时候就可以根据你的需要直接从map中获取到一个实际的业务对象用于测试的时候使用了,最后记得要在测试完成后要在tearDown中清除初始化的数据。这样处理后我发现在测试时就感觉到很方便了,用到什么直接从map中取就可以了。
也许有人会说这样做不还是是集成测试了吗,你build的时候需要数据库、持久层啊什么的,这里我不想来争论究竟是属于单元测试还是集成测试,因为它属于什么对于我们的功能来说是没有意义。无论什么测试的最终目标就是让我们的功能可用。
至于构建环境的实现我只是给出了一个对于我当前项目代价最小的方法,其实如果你的项目不是使用静态方法的话,可以考虑构建一个完全mock的环境这样就可以称之为单元测试了。
而且对于这个InitialTestObject我觉得可以做成一个开源的小工具,支持各种不同的持久层(jdo,hibernate),然后根据我们定义的持久层模型做为我们的业务规则,就不需要自己编写具体的初始化规则代码了,你只需要写xml数据并指定好对应的持久层模型,希望大家可以对这个想法对提提建议,也许已经有人做了,那我就不做重复功了。
下篇预告:think in refactor 时间:待定
posted on 2007-09-13 00:35
rocket 阅读(1005)
评论(1) 编辑 收藏