2008-01-16
俺摸,俺摸,俺默默摸
猪肉炖粉:“那啥,猪哥啊,这两天你身价大涨,发了吧?忙啥呢?”
一只猪:“可不是!到哪儿都被采访,这名猪也有隐私权滴!最近特想过普通猪的生活。这不,洗尽铅华,老老实实地躲圈里整Java呢”
话说这Java的一级摸客(EasyMock),老猪最近用的满多的。在Java 4里面不忍卒睹的代码在java 5里面骤然变得性感许多。不过用的多了,也发现有些不方便的地方。最不爽的就是:俺老猪不是粗心吗?有时候不小心就会忘了EasyMock.verify()或者IMocksControl#verify()。
这一忘了不打紧,有些bug就藏在那,测试也过了,但是bug也没找出来。
有很多淫说这还不容易?用IMocksControl,然后在tearDown()里写control.verify(),就没事了。(不好,被你发现老猪还在用回立牌JUnit 3.8)
嘿嘿,老猪针对这种左倾机会主义思潮做出了最坚决的斗争。
为啥?且听老猪我慢慢到来。在tearDown()里面写verify()有三个很致命的毛病:
1。 JUnit 3.8的tearDown()相当于try-finally里面的finally。也就是说,即使你的test出现了异常,它也会被执行。因此如果你的测试代码还没等到verify()的时候就因为某种原因歇菜了(比如,某个assertEquals()失败了),这个异常会被吞噬掉,你得到的将会是一个毫无意义的EasyMock的verify()异常。
2。tearDown()很有可能被子类重载滴。万一子类忘记了调用super.tearDown()怎么办?”子类不应该忘“?呵呵,要我说你还不如干脆就”不应该“忘记调用verify()呢。这不是前门驱虎,后门进狼么?
3。不能不分3*7=21就verify呀同志!咱假如说,俺老猪懒,为了跑到绿草如茵的山坡睡个暖洋洋的懒觉,写了一个啥也不干的testStone(),反正回头就说这山叫石头山,山上有个石头洞,洞里有俩和尚在讲故事...(说走嘴了),迷迷糊糊闭着眼睛哼着小曲点击了一下my precious testStone()。“啦啦啦啦啦,啦啦啦啦,天空出彩霞呀,.哦?.哦.bug出来啦呀
”。啥?居妍说俺的testEmpty错了?俺老猪是无辜地呀。因为俺啥也没干啊!是猴哥。没错,肯定是这弼马温!说啥不能还没replay()呢就verify()?废话,我也没让你verify呀。这个故事告诉我们,不能没事就verify(),你至少得知道人家replay()了没有先。
老猪的解决办法是做一个PorkMockTest类,然后在TestCase#runTest()上做文章:
这个代码还比较简陋,还不处理strict和nice mock。不过呢,基本上就剩照猫画虎了——当然,我没跟你说就copy&paste啊,你怎么也得refactor一下才好意思见人吧?
好了,现在只要你继承我这个PorkMockTest,你就可以一直往前走,不用往两边看了。你可以理直气壮地忘掉verify()——要求我们懒惰如猪的程序员记住计算机可以搞定的东西是犯罪呀,对人民赤果果地犯罪!
好,现在我可以这么写了:
欢乐的时光总是过得快,又到时间说白白。不要走开,广告之后请继续收看俺摸(mock),俺摸,俺默默摸!
一只猪:“可不是!到哪儿都被采访,这名猪也有隐私权滴!最近特想过普通猪的生活。这不,洗尽铅华,老老实实地躲圈里整Java呢”
话说这Java的一级摸客(EasyMock),老猪最近用的满多的。在Java 4里面不忍卒睹的代码在java 5里面骤然变得性感许多。不过用的多了,也发现有些不方便的地方。最不爽的就是:俺老猪不是粗心吗?有时候不小心就会忘了EasyMock.verify()或者IMocksControl#verify()。
这一忘了不打紧,有些bug就藏在那,测试也过了,但是bug也没找出来。
有很多淫说这还不容易?用IMocksControl,然后在tearDown()里写control.verify(),就没事了。(不好,被你发现老猪还在用回立牌JUnit 3.8)
嘿嘿,老猪针对这种左倾机会主义思潮做出了最坚决的斗争。
为啥?且听老猪我慢慢到来。在tearDown()里面写verify()有三个很致命的毛病:
1。 JUnit 3.8的tearDown()相当于try-finally里面的finally。也就是说,即使你的test出现了异常,它也会被执行。因此如果你的测试代码还没等到verify()的时候就因为某种原因歇菜了(比如,某个assertEquals()失败了),这个异常会被吞噬掉,你得到的将会是一个毫无意义的EasyMock的verify()异常。
2。tearDown()很有可能被子类重载滴。万一子类忘记了调用super.tearDown()怎么办?”子类不应该忘“?呵呵,要我说你还不如干脆就”不应该“忘记调用verify()呢。这不是前门驱虎,后门进狼么?
3。不能不分3*7=21就verify呀同志!咱假如说,俺老猪懒,为了跑到绿草如茵的山坡睡个暖洋洋的懒觉,写了一个啥也不干的testStone(),反正回头就说这山叫石头山,山上有个石头洞,洞里有俩和尚在讲故事...(说走嘴了),迷迷糊糊闭着眼睛哼着小曲点击了一下my precious testStone()。“啦啦啦啦啦,啦啦啦啦,天空出彩霞呀,.哦?.哦.bug出来啦呀
老猪的解决办法是做一个PorkMockTest类,然后在TestCase#runTest()上做文章:
public class PorkMockTest extends TestCase {
private IMocksControl control = null;
private boolean replayed = false;
private boolean verified = false;
@Override protected void runTest() throws Throwable {
super.runTest();
if (replayed && !verified) {
verify();
}
}
private IMocksControl control() {
if (control == null) {
control = EasyMock.createMockControl();
}
}
public <T> T mock(Class<T> type) {
return control.createMock(type);
}
protected void replay() {
control().replay();
replayed = true;
}
protected void verify() {
verified = true;
control().verify();
}
}
这个代码还比较简陋,还不处理strict和nice mock。不过呢,基本上就剩照猫画虎了——当然,我没跟你说就copy&paste啊,你怎么也得refactor一下才好意思见人吧?
好了,现在只要你继承我这个PorkMockTest,你就可以一直往前走,不用往两边看了。你可以理直气壮地忘掉verify()——要求我们懒惰如猪的程序员记住计算机可以搞定的东西是犯罪呀,对人民赤果果地犯罪!
好,现在我可以这么写了:
public class LionHeadTest extends PorkMockTest {
public void testHuoHou() {
LionHead head = mock(LionHead.class);
head.bite();
replay();
cook(head);
// 忘记吧,忘记吧。忘记是一种幸福。能忘记的人才能快乐地吃狮子头啊!
}
}
欢乐的时光总是过得快,又到时间说白白。不要走开,广告之后请继续收看俺摸(mock),俺摸,俺默默摸!
评论
ajoo
2008-01-21
kjhot 写道
easymock2.0好像不支持对一个返回值为空的方法期望抛出一个异常,他的IExpectationSetters只有在返回值不为空的时候才能addThrow,这个有点很不爽!
EasyMock.expectLastCall().andThrow()?
kjhot
2008-01-21
easymock2.0好像不支持对一个返回值为空的方法期望抛出一个异常,他的IExpectationSetters只有在返回值不为空的时候才能addThrow,这个有点很不爽!
Sam1860
2008-01-20
那是框架应该解决的问题,jmock就自动verify了。
ajoo
2008-01-18
hax 写道
EasyMockTemplate 如何?
不好,不好。一个replay()很清楚地标示了expectation。要是怕看不清楚,放几个空行和传说中的神秘分隔符也足够了。
匿名类的语法实在比较烦。不值当的。
hax
2008-01-18
EasyMockTemplate 如何?
ajoo
2008-01-17
kongxx 写道
忘记verify(),那如果写test的时候忘了assertXXX(...),那情形不是一样么。写Unit测试的第一步不是先写出测试失败的Unit Case么?
一样么?不一样吧?用assert,你要不就没写assert,也就是说你的需求意图根本没有表现在代码中,要不就写了这么一行来表达这个需求。
verify不同啊。你的需求是那些写在replay()之前的expectation。你期望foo()被调用,就写一个foo()。但是即使你根据需求写了这么多期望,如果你忘了verify(),也还是没用功。
打个比方,你要是忘了上班,不发你工资天公地道。但是如果你确实上班了,但是公司还要求你每天都到内部网上写一个“是的,我今天的工作不是无偿的,请付给我工资”,那么这个“忘记”就比较讨厌了是不?
我承认TDD会减轻“忘记”的问题。但是,不绝对吧?对下面一个测试:
int runFoo(Foo foo) {
return 0;
}
void testFoo() {
Foo foo = mock(Foo.class);
expect(foo.run()).andReturn(1);
replay();
assertEquals(1, runFoo(foo));
}
它也变红,因为assertEquals()不通过。把runFoo()改成return foo.run(),就绿了。什么机会让你能够意识到verify()忘了呢?
kongxx
2008-01-17
忘记verify(),那如果写test的时候忘了assertXXX(...),那情形不是一样么。写Unit测试的第一步不是先写出测试失败的Unit Case么?
bulargy
2008-01-17
生动啊~~~喜欢那个
// 忘记吧,忘记吧。忘记是一种幸福。能忘记的人才能快乐地吃狮子头啊!
呵呵
// 忘记吧,忘记吧。忘记是一种幸福。能忘记的人才能快乐地吃狮子头啊!
呵呵
rasonyang
2008-01-17
不错!幽默!
发表评论
提醒: 该博客已发表在公共论坛,博客所有留言会成为论坛回贴,留言请注意遵守论坛发贴规则
- 浏览: 179861 次

- 详细资料
搜索本博客
最近加入圈子
最新评论
-
动态properties转换
恩,不错,method.getReturnType 都用上了。动态代理的价值全被 ...
-- by upyaya -
动态properties转换
apache beanutils中 dwr中 jsf myfaces中 都有基 ...
-- by kimmking -
动态properties转换
签名,泛型,代理 都是自己平时很少用到的,运行一下,学习一下
-- by soleghost -
动态properties转换
呵呵,精益求精啊,不过有个地方参数顺序好像错了: public final c ...
-- by racnow -
动态properties转换
感觉可以参考spring里面的类型转换吧,它好像用的是java的Property ...
-- by yufu






评论排行榜