|||
在单元测试中,为了集中测试目标模块A,常常需要模拟(Mock)A所用到的方法或类。例如,已知2016年5月11日是周三,我们建立一个名为calcWeek的模块,用于计算任意输入的x年x月x日是星期几,那么,我们首先要计算x年x月x日 - 2016年5月11日 = ?天. 首先,这需要判断x年x月x日是否为闰年,我们需要专门写一个函数isLeapYear来完成此项功能。假定isLeapYear还没有完成,我们又需要测试calcWeek模块的主题功能,这时就可以简单地mock一个isLeapYear,比如,令其直接返回True。这样看起来,Mock一个函数并非困难的事情,那么,为什么还需要大费周折地建立像EasyMock这样的工具箱呢?
其实,理由很简单,如果被测试的模块calcWeek是一个黑盒呢?在这个黑盒中,calcWeek认为isLeapYear在包a.b.c的类MyYear中,也就是它import了包a.b.c,这样,我们随意Mock的isLeapYear肯定就不会被调用,除非我们把isLeapYear的Mock实现直接放入包a.b.c的类MyYear中,但这又把测试代码和被测试代码混在了一起。
所以,简单Mock一个对象或方法是很简单的,但让我们所Mock的对象和方法按照被测试模块既定的调用方式被调用才是困难的,而后者,就是EasyMock这样的工具箱做的事情,其真正核心的功能是:拦截那些尚未实现或不期望被真实调用的对象和方法,并为其设置预定义的行为。例如:
IMocksControl control = EasyMock.createControl();
MyYear mock_MyYear = control.createMock(a.b.c.MyYear.class);
mock_MyYear.isLeapYear(); // 模拟调用
expectLastCall().andStubReturn(True); // 拦截返回值,将其设置为我们所预期的返回值
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-6-16 20:53
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社