這兩天彷彿遊歷一趟精彩的罐頭地獄(Jar Hell)。本以為可以很簡單的結合最新的JUnit 4.x+Spring 2.5.x+Eclipse(好啦!我承認有點舊,是用3.4.1版)作一個Spring JUnit的Demo,哪知弄了快兩天。

  事情是這樣,被主管要求弄一個簡單的JUnit的Sample簡報。但事實沒那麼簡單,若是要做給Developers看的Best Practice白箱測試,不是弄一個Calculator飯粒就可以唬弄。想想看,Java專案系統的開發,比例最多的是什麼組合?IDE是Eclipse拔頭籌,核心框架非Spring莫屬,再延伸一下就有前後端的需求,但比較多樣,前端有Struts、Struts2、JSF、Flex等…,後端雖近期有JPA想統一江湖,但ORM的Hibernate、iBatis、TopLink和JDO各領風騷,非ORM的有Spring JDBC、甚至直接拿JDBC搭配個Pool也算;而測試工具雖然也jMock出現,但仍是JUnit獨占鰲頭,而且互不抵觸,與jMock分居於白箱與黑箱測試龍頭。哈拉完畢,以下開始精彩的Jar Hell之旅,就單純的結合JUnit+Spring+Eclipse:

  為Demo不失真,就拿最近的吉隆坡專案作為JUnit的簡報。當我找到網頁這麼寫如下,不由得意覺得真容易:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"/applicationContext.xml"})
public class YourTest {
 @Autowired
 private MasterDAO masterDAO;
 
 @Test
 public void testList() {
  this.masterDAO.findAll();
 }
}

  哪知就壞在上面劃底線的類別。錯誤訊息是:class "junit.framework.JUnit4CaseRunner"'s signer information does not match signer information of other classes in the same package。經過Google指示,會是有兩個JUnit Library衝到,可是確認我並沒有用Add Library把JUnit加進來,而不管是用Maven或是單純import junit.jar,執行[Run As]->[JUnit Test]還是有同樣的錯。

  咦!後來看到JUnit Test怎麼被加粗了XD,那Eclipse所Run是哪個版本?是plugin,我找到plugin裡的junit.jar解壓縮,哇勒!一樣叫JUnit 4.4,但它是偷工減料版,竟沒有JUnit4CaseRunner這個類別,但在Eclipse 3.5裡附的junit.jar就有,而SpringJUnit4ClassRunner就是繼承JUnit4CaseRunner。所以後來我在plugin目錄換上真材實料的junit.jar,問題就解決了,另一個問題又發生了:

java.lang.NoSuchMethodError: org.springframework.core.annotation.AnnotationUtils.findAnnotationDeclaringClass(Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/Class;

  上述是情況由SpringJUnit4ClassRunner丟出的,Google說明是有引用到Spring 2.0.x版所致,但我也再次確定沒引用到2.0.x,可是後來想到吉隆坡這案也確實是用2.0.6版,而我除了referece jar file list,我也reference project。後來我就把project包成jar,不含lib,移除對project的reference改import包好的jar,果然是reference project的問題。

  Google指示出錯機率極微,就是難在不知你的情況是在哪裡發生的。不否認JUnit 4.x和Maven 2.x已經進步神速,但Eclipse的版本差0.09(v3.5 – v3.4.1)就差那麼多。切~~~!

  題外話。現在高談闊論SOA和Cloud Computing,為的是universal interface、universal service。但一樣都用Java開發,越複雜的系統就越難逃Jar Hell的魔咒,就欠缺一味:universal middleware。

arrow
arrow
    全站熱搜

    Jemmy 發表在 痞客邦 留言(0) 人氣()