EasyMock(应用于SSH):
EasyMock用途很简单,帮你模拟接口,你可以预定义一些对象的行为,在测试代码的时候使用模拟的对象。在这里我们关心的仅仅是自身的代码逻辑而不是外在的服务和对象。
首先,web层中pom.xml中需要添加easymock包依赖
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>3.4</version>
<scope>test</scope>
</dependency>
单元测试基本原则:
-
隔离:这是初衷,也是单元测试的根本要求
-
Just Enough:够就行了,别少,但也别多
-
Interaction-based:与之相对的,Stub是state-based
-
Expection:事先总有期待,期待方法有没有被调用,期待适当的参数,期待调用的次数,甚至期待mock间调用顺序
单元测试基本语法:
Step1. record阶段,记录对若干依赖对象的期望
o= EasyMock.createMock(MyAdd.class); //创建Mock对象
EasyMock.expect(o.add(1,1)).andReturn(2); //对mock对象,提出期望
Step2. Replay阶段,创建测试主对象,并添加依赖对象进去
EasyMock.replay(o); //期望设置完毕,进入replay阶段
xxx.set(o);
Step3. Verify阶段,验证测试结果与交互行为
assertEquals(2, o.add(1,1));
assertNotNull();
EasyMock.verify(o); //对mock对象执行验证
EasyMock简单语句:
request = EasyMock.createMock(HttpServletRequest.class);
response = EasyMock.createMock(HttpServletResponse.class);
scontext = new MockServletContext();
第一行声明一个Mock来模拟HTTP Request请求。
第二行相同原理来模拟HTTP Response请求。
第三行模拟context
在项目中,我们首先创建一个BaseController基类,上面三行函数就是声明在基类中的分别去模拟对象的行为。
easymock还可以来模拟value stack(如下面代码所示)。
StockMarket marketMock = EasyMock.createMock(StockMarket.
class
);
EasyMock.expect(marketMock.getPrice(
"EBAY"
)).andReturn(
42.00
);
EasyMock.replay(marketMock);
第三行当调用 replay() 方法时,我们激活了Mock对象。
注意事项:
1. 既然设了期望,下面(即Step2)就要测到,否则别设置;
2. 参数设了什么,就要传什么;说了返回什么,就要返回什么;
3. 对异常的测试,别忘了(见拓展里2);
4. 以上说的都是,要Mock Interface(非具体Class),那如何Mock Class呢?用法同上Step1-Step3,只是引入的Jar包不同。Mock Interface—org.easymock.*, Mock Class—org.easymock.classextension.*
5. 建议使用3.0及以上版本
6. Mock Interface/Class还是有些限制的:
- 不能mock final方法
- 不能mock static方法
- 不能mock private方法
- 不能mock这些个特殊方法:equals(), toString(), hashCode()
7. EasyMock.createMock(), createNiceMock(), createStrictMock()
EasyMock.createControl(), createNiceControl(), createStrictControl()
(1)不检查调用次序,不检查调用次序&&对于意料之外的调用返回0/null/false,检查调用次序
(2)strict,对于一个对象的方法间检查次序,不同对象的方法间,却没检查。要想检查也可以,用strict control。
(3)createMock(name, Class),带上name这个字段,可以测试执行失败时的异常信息里看到mock对象名称。