我要投搞

标签云

收藏小站

爱尚经典语录、名言、句子、散文、日志、唯美图片

当前位置:大家发高手网 > 断言 >

从“用断言检查 null”到“设计单元测试”

归档日期:05-13       文本归类:断言      文章编辑:爱尚语录

  防御式编程是保护自己的程序不受外部侵害的一种有效方式。代码大全在“防御式编程”这一章中讲到,可以用断言(assert)来检查真实情况是否满足自己的预期,例如指针非空。

  上个月Miško Hevery写了一篇文章:断言,还是不断言,描述了在构造器中编写断言给单元测试所造成的种种不便。

  然后说到,因为 secure 方法只需要 door 和 window 两个对象,所以理所当然的是,在测试这个方法的时候只需要初始化 door 和 window,其他参数用 null 代替,如: 、

  这样的方法才能够让人看明白意图,但是因为构造器中做了参数非空的断言,所以就不得不这样初始化 House 对象:

  这样就让人不太能看得懂到底是哪些对象真正在测试方法中被用到了。而当构造器中的参数增多,代码的可读性就会更差。Miško 最后提到:

  有不少人跟帖反对 Miško 的观点,他们认为这根本不是断言的问题,而是来自于设计本身,例如

  不管是我写的代码,还是我看到的代码,都是在调用对象的时候去做断言,而不是在保存对象的时候。这样合理不?所以你应该在 secure() 方法里面写 Assert.notNull(door);Assert.notNull(window)。用到的时候再去检查,而不是提前 就把一切都检查好,以备过几天以后需要用。

  这样问题就很好的解决了,其他变量都可以在 HouseBuilder 里面提供一些缺省值,你也不会创建出具有非法状态的对象来。

  所以你的测试人员就得了解方法的具体实现,而这是不应该的……我如果有个可以滑开的房顶,我就得还给它上锁,可现在房顶是 null。

  后面有几个人同意 earlNameLess 的看法:测试代码需要清楚的了解实现代码的内部实现方式实在不是什么好做法。建议根据具体情况提取出接口,或者用一下 Ioc 容器。

  上面有很多讨论都是针对 Misko 的测试代码不得不知道实现细节这个做法的。虽然,测试代码了解内部细节是有点不太稳定,但这是单元测试,单元测试是白盒 测试,不是黑盒。如果你用 mock,那你肯定得知道内部细节……再说的清楚一点,你是在测试基于给定的条件,你的代码能够得到预期的结果。你必须得知道这 些条件是啥,把那些不满足的条件排除掉。

  如果有人来改了实现细节,那测试就会失败。不过这也暴露出一个问题来,你必须得有一整套单元测试可以做回顾。如果我改了行为,我也就修改了测试的意图。然后我就得修改测试,让它对新的假设起作用。

  跑题跑了一阵子以后,rnaufal回到原来话题上,直接抛出了 JDK 文档:

  读者朋友,你在自己的代码中使用防御式编程么?用过 assert 来检查 null 与否么?你的单元测试是在检查行为,还是检查输入输出呢?欢迎分享你们的意见。

本文链接:http://buffaloruse.net/duanyan/353.html