说一下EasyMock
用了很长的时间,终于写出了合乎标准的单元测试。好吧,我就是做事情不够细致,所以才这么大费周折。。。
关于测试
- 做测试者,一定要弄清出不同种类测试的分别,弄清楚什么是Unit Test,什么是Intergration Test, Perfermance Test, Function Test. 不然,就相当于没有测试。
- Unit Test是程序员完成,Intergration Test通常也是程序员。而Perfermance Test和Function Test则应当由专业的QA人员去做,当然如果有人多才多艺全部完成,那没有问题。
- 验收测试Validation Test 应当由用户按照SOW定义完成,当然,这也是理想的情况——我们有清晰的需求,严格控制的变更。应用XP的场合,这更多应当是庆功宴前的走形式。
为什么这么关心测试
- 测试是开发的标杆,里程碑,没有测试,就没有提交件。
- 测试是风险管理的最直接手段,良好的测试体系和执行力是软件项目中重要的技术性保障手段。
- 测试保证项目的完成,在项目发生变更时控制风险。
Martin Fowler写过一个故事 TestCancer ,描述了一个结构精巧,测试完美的应用如何生病而无可就要的。而我们一旦一时一刻放弃这些准则,就会陷入无以复加的尴尬境地,所以,在动手写代码前,特别是所谓的高级人员,先打好基本功,您的一个轻率决定,或者经验之谈,就会让整个团队陷入MASS.
关于EasyMock
使用了EasyMock感觉不错,就着代码说说使用中遇到的两个问题:
问题1 没有设置返回值
java.lang.IllegalStateException: missing behavior definition for the preceeding method call findByExample(<any>)
对于有返回值的方法,要设定预期返回值。
@Test
public void testRegist() {
User user = new User();
user.setUserId("testUser");
user.setPassword("password");
//下面这行代码去掉 .andReturn(null)就会报上面的错误。
expect(mock.findByExample(anyObject())).andReturn(null);
expect(pwe.encodePassword(eq(user.getPassword()), anyObject()))
.andReturn("password");
expect(mock.save(anyObject())).andReturn(1);
replay(mock);
replay(pwe);
userService.regist(user);
}
问题2 参数匹配问题
java.lang.IllegalStateException: 2 matchers expected, 1 recorded.
对于EasyMock会对传入Mock对象方法中的参数进行比较,也就是调用equals或者==引用比较等等。如果不能正确设置比较的行为,就会造成参数不匹配。EasyMock提供了一些方法来定义如何匹配参数,请参考
EasyMock文档
@Test
public void testJoinGame() {
Game expGame = new Game();
expGame.setId(1);
expGame.setCreateUser(new User());
expGame.setGameStatus(GameStatus.NOT_START);
expGame.setPlayer(new ArrayList());
//这行代码如果写成
// expect(publicDao.get(Game.class, anyLong())).andReturn(expGame);
//就会出现前文的错误
expect(publicDao.get(eq(Game.class), anyLong())).andReturn(expGame);
publicDao.update(expGame);
replay(publicDao);
gameService.joinGame(1, new User());
verify(publicDao);
}
