俺摸,俺摸,俺默默摸 (2)

那啥?刚才说到哪了?“如云朵般的呵护”?下面谁说的?给我拉出去好好“呵护呵护”!

人家没那么说啦!讨厌!是刚才广告里说的嘛!我说刚才我们“俺摸”系列说到哪了?
对了,说到我们可以这么用PorkMockTest:

[code]
public class LionHeadTest extends PorkMockTest {
public void testHuoHou() {
LionHead head = mock(LionHead.class);
head.bite();
replay();
cook(head);
// 忘记吧,忘记吧。忘记是一种幸福。能忘记的人才能快乐地吃狮子头啊!
}
}
[/code]

那要是俺老猪比较馋(好像不需要“要是”了?),就好狮子头这口,连写了八个test都要mock(LionHead.class)怎么办?俺以前都这么写:

[code]
public class LionHeadTest extends PorkMockTest {
private final LionHead head = mock(LionHead.class);

public void testEat() {...}
public void testEatAgain() {...}
public void testOneMorePlease() {...}
...
}
[/code]

不过后来在喜欢作JUnit专家状的沙师弟的唠叨下,已经不敢再明目张胆地这么做了。据丫说吧:“JUnit 3.8下,所有TestCase的构造函数都是在TestSuite创建的时候调用的,所以不要在构造函数里做任何可能比较慢或者可能抛exception的动作,否则,一旦发生异常,错误信息是惨不忍睹地不知所云!!!”。在Google上搜索出来的结果也似乎站在这个喜欢冒充高手的家伙那边,让我真想打他的脸啊,打他的脸。

哎,我真想揪住某个洋洋得意写了《Test Driven Development》的人的领口,啐他一脸。凭啥非要恶心俺老猪?招你啦?

于是,俺只好捏着鼻子在这个讨厌的家伙的监督押送下返工:
[code]class LionHeadTest extends PorkMockTest {
private LionHead head;

@Override protected void setUp() throws Exception {
super.setUp();
head = mock(LionHead.class);
}

...
}
[/code]

靠!这是一砣什么屎?于是,除非实在饿的不行了,俺老猪宁可在每个test里面调用一遍mock(LionHead.class)也懒得搞这么一砣东西出来。

这不?昨天听师傅讲楞加经(楞要加塞儿经?),迷迷糊糊又睡着了,等猴哥拎着耳朵(当然是他自己的耳朵,敢拎我的?哼哼,现在俺这肉可贵了,掂量着自己赔的起先!)把俺叫醒,正好听见师傅不小心把经文夹缝里的字儿给念出来几个。然后俺就觉得小腹一股热气冲上丹田,瞬间增加了几个甲子的功力。然后体力,智力,根骨,悟性都增加5点。任督二脉无师自通。这个讨厌的问题也终于找到了一个解决方案,哈哈。

长话短说,我想到了用annotation的方法。只要在PorkMockTest里面加上一点反射的咚咚,我就可以这么写了:
[code]
public class LionHeadTest extends PorkMockTest {
@Mock private LionHead head;

public void testEat() {...}
public void testEatAgain() {...}
public void testOneMorePlease() {...}
...
}
[/code]
比我原来的那个版本还爽,现在我都不用车轱辘话把LionHead说两遍了!那么PorkMockTest怎么搞的呢?南无阿弥陀佛:

[code]
@Target(FIELD)
@Retention(RUNTME)
protected @interface Mock {}

@Override public void runBare() {
mockFields(getClass(), this);
super.runBare();
}

private void mockFields(Class cls, Object obj) {
Field[] fields = cls.getDecalredFields();
for (Field field : fields) {
if (field.getAnnotation(Mock.class) != null) {
field.setAccessible(true);
field.set(obj, mock(field.getType());
}
}
Class superclass = cls.getSuperclass();
if (superclass != null) {
mockFields(superclass, obj);
}
}
[/code]

几个可能的问题回答一下:
1。为什么用runBare()而不是runTest()?因为我希望所有的@Mock fields在setUp()之前就初始化好,这样子类在setUp()里面就可以为所欲为了。
2。这样的速度是不是比较慢?毕竟每个test都要跑一下runBare(),也就都要跑一下这些反射代码?是的。真实代码是用了一个cache来缓存每个class的所有@Mock field。不过这种技术细节我就不展开了。

现在的PorkMockClass不要太好用,尤其是需要用到很多mock的类。老猪俺想吃啥就mock啥。什么龙虾,鲍鱼,燕窝,象拔蚌,都不在话下。
[code]
public class FeastTest extends PorkMockTest {
@Mock private Lobster lobster;
@Mock private Oyster oyster;
@Mock private BirdNest nest;
@Mock private ElephantNoseClam clam;

...
}
[/code]

俺摸,俺摸,俺使劲儿摸!哈哈。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值