锁定老帖子 主题:TDD:mock还是build
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-09-13
记得我以前写过一个文章是有关于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调用到的数据究竟是什么了,于是就可以对你期望获得的结果和经过实际方法得到的结果进行对比验证了。 我发现其实在测试的时候我更加关注的是业务数据的build,而系统架构通常是服务于业务的。所以我就开始考虑,能否有个方法构建出最基本需要的业务模型数据呢。查阅了一些网上工具,发现没有能够满足我当前需求(kodo做持久层,还有我们自己研发的知识引擎),于是就自己简单做了一个InitialTestObject,想法很简单就是通过一个xml文件然后根据已知的业务模型结构定义好数据,然后根据固定的规则初始化好业务数据,并且存放到一个map中去(方法比较简单我就不列出源码了),然后再使用时把初始化放到setUp中去,这样在测试的时候就可以根据你的需要直接从map中获取到一个实际的业务对象用于测试的时候使用了,最后记得要在测试完成后要在tearDown中清除初始化的数据。这样处理后我发现在测试时就感觉到很方便了,用到什么直接从map中取就可以了。 也许有人会说这样做不还是是集成测试了吗,你build的时候需要数据库、持久层啊什么的,这里我不想来争论究竟是属于单元测试还是集成测试,因为它属于什么对于我们的功能来说是没有意义。无论什么测试的最终目标就是让我们的功能可用。 至于构建环境的实现我只是给出了一个对于我当前项目代价最小的方法,其实如果你的项目不是使用静态方法的话,可以考虑构建一个完全mock的环境这样就可以称之为单元测试了。 下篇预告:think in refactor 时间:待定 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-09-13
mock对象会出现很多层次的时候,首先要考虑是不是对象设计上的问题。正常的建模,层次不会太深的。
但是的确会出现这样的问题,比如说写一个powerpoint的插件,powerpoint提供了一个shape->slide->presentation的树状层次。如果我们把这些对象都mock的话,就会出现非常深层次的expect。对于这样的问题,我的解决方案是手写stub。然后用state based的测试来做测试。 对于你说的持久层依赖的问题,你的领域对象就不应该依赖于DAO。正确的做法是像hibernate那样,用proxy模式来隔离持久化逻辑和业务逻辑。1 |
|
返回顶楼 | |
发表时间:2007-09-13
taowen 写道 mock对象会出现很多层次的时候,首先要考虑是不是对象设计上的问题。正常的建模,层次不会太深的。 非常感谢你的建议,有些方法是我开始解决的时候没有想到的。但是的确会出现这样的问题,比如说写一个powerpoint的插件,powerpoint提供了一个shape->slide->presentation的树状层次。如果我们把这些对象都mock的话,就会出现非常深层次的expect。对于这样的问题,我的解决方案是手写stub。然后用state based的测试来做测试。 对于你说的持久层依赖的问题,你的领域对象就不应该依赖于DAO。正确的做法是像hibernate那样,用proxy模式来隔离持久化逻辑和业务逻辑。1 我开始的想法就是很简单,就是最快的解决mock代价的问题。 而stub的缺点就是对模拟的维护,有时候你会发现对于stub的维护甚至超过了待测的方法维护。 另外,对于proxy模式来隔离的方法确实应该是这样做,但是由于接手的系统结构已经是这样了,而且比较庞大所以这种改动代价会很高很高。 所以我现在看agile的时候是一种这样的想法,很多时候很多问题不是对不对,合不合适来看的,而是如何在代价和质量之间能够找到一个较好的平衡点。因为这样的平衡点将更为“可靠”一些。 |
|
返回顶楼 | |
发表时间:2007-09-13
没太看明白你的意思,似乎跟dbunit做的工作一样
|
|
返回顶楼 | |
浏览 4478 次