前面的例子中,mock的對象都是基于interface,雖然說我們總是強調要面對接口編程,而不要面對實現,但是實際開發中不提取interface而直接使用class的場景非常之多。尤其是一些當前只有一個明確實現而看不到未來擴展的類,是否應該提取interface或者說是否應該現在就提取interface,總是存在爭論。
這種情況下,我們就會面臨主要測試對象依賴到一個具體類而不是interface的情況,easymock中通過class extension 來提供對class mocking的支持。
1. class mocking的使用
easymock class extension的使用方式和普通的interface mock完全一致,基本上easymock中有的功能easymock class extension都同樣提供,而且所有的類名和方法名都保持一致。
ClassA impl = Easymock.createMock(ClassA.class);
Easymock.expect(impl.getById("1001")).andReturn(...);
Easymock.replay(impl);
唯一的差異在于,easymock class extension的java package和easymock不同,easymock是org.easymock.*, 而 easymock class extension是org.easymock.classextension.*,典型如 org.easymock.classextension.Easymock 對應 org.easymock.Easymock。另外在發布時,兩者是分開發布的,easymock.jar 和 easymockclassextension.jar,需要根據需要分別導入,或者必要時同時導入。
2. 3.0新版本和向后兼容
我們來回顧一下easymock的歷史版本: easymock 1.* 非常久遠了,已經沒有人在用。2.0版本在2005-12-24發布,基于jdk1.5,之后陸續發布的2.1/2.2/2.3/2.4/2.5等幾個版本中,都提供了對應版本的easymock class extension。easymock 3.0 版本是最新版本,2010-05-08 發布,主要改進就是將easymock class extension的功能合并到easymock中,以后只要使用easymock就可以提供class mocking的功能。當然為了兼容2.*下的舊代碼,依然提供了EasyMock 3.0 Class Extension代理到easymock 3.0。
3.0版本之后,easymock class extension的class mocking功能已經無縫集成到easymock中,因此代碼的編寫簡潔了很多,強烈建議新用戶直接使用3.0版本。對于使用2.*版本的舊有代碼,easymock提供了easymock class extension的3.0版本,兼容2.*的代碼,底層實現實際是代理給easymock3.0。因此2.*版本easymock class extension的用戶可以通過簡單的升級easymock class extension到3.0即可平滑升級,之后再逐漸替換掉easymock class extension的代碼。
3. class mocking的限制
class mocking是有一些限制的,
1) 不能mock類的 final方法
如果final方法被調用,則只能執行原有的正常代碼。
2) 不能mock類的static 方法。
同樣如果private方法被調用,只能執行原有的正常代碼。
3) 不能mock類的一些特殊方法: equals(), toString()和hashCode().
原因是easymock在實現是為每個class mock對象提供了內建的以上三個方法。需要強調的是,對于基于interface的mock,這個限制也是同樣存在的,即使以上三個方式是interface定義的一部分。
在使用時需要避開這種場景,或者組合使用其他的mock 框架比如jmockit來mock private方法和final方法。