饒榮慶 -- 您今天UCWEB了嗎?--http://www.ucweb.com

          3G 手機(jī)開(kāi)發(fā)網(wǎng)

             :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
            99 Posts :: 1 Stories :: 219 Comments :: 0 Trackbacks
          雖然以前用easymock測(cè)試過(guò)Dao,但那些Dao的實(shí)現(xiàn),要么就hibernate,要么就用spring,而這兩個(gè)框架的執(zhí)行正確與否我們是不用關(guān)心的。JDBC是不是也這樣測(cè)試了。答案是肯定的。
          ????? 這幾天要用存儲(chǔ)過(guò)程跟jdbc來(lái)做個(gè)項(xiàng)目,想想也有好長(zhǎng)一段時(shí)間沒(méi)用過(guò)JDBC來(lái)做項(xiàng)目了。該復(fù)習(xí)復(fù)習(xí)了。
          ????? 前陣子學(xué)了easymock,真好現(xiàn)在可以派上用場(chǎng)了。不過(guò)在測(cè)試的過(guò)程中還是遇到了不小問(wèn)題,想來(lái)是自己基礎(chǔ)不好的緣故。

          ?????? 這次不TDD了,太麻煩了。
          ?????? 先看看我們要測(cè)試的代碼
          ?????
          java 代碼
          ?
          1. CallableStatementcstmt?=?null;??
          2. ????????try?{??
          3. ????????????cstmt?=?_conn.prepareCall("{call?LUCK_LOAD_COMMON(?,?)}");??
          4. ????????????cstmt.setString(1,?"1");??
          5. ????????????cstmt.registerOutParameter(2,?java.sql.Types.VARCHAR);??
          6. ??
          7. ????????????cstmt.executeUpdate();??
          8. ????????????return?cstmt.getString(2);??
          9. ??
          10. ????????}?catch?(Exception?e)?{??
          11. ????????????GxDebug.logException(e);??
          12. ????????????e.printStackTrace();??
          13. ????????????return?null;??
          14. ????????}?finally?{??
          15. ????????????if?(cstmt?!=?null)??
          16. ????????????????try?{??
          17. ????????????????????cstmt.close();??
          18. ????????????????}?catch?(Exception?e)?{??
          19. ????????????}??
          20. ????????}??
          ? 代碼還挺長(zhǎng)的。從上面的代碼我們知道我們必須mock兩個(gè)對(duì)象進(jìn)去。一個(gè)是Connection, 一個(gè)是CallableStatementcstmt 。
          好再看看我們的測(cè)試代碼
          java 代碼
          1. conn.prepareCall("{call?LUCK_LOAD_COMMON(?,?)}");??
          2. ????conControl.setReturnValue(cstmt);??
          3. ????conControl.replay();??
          4. ??????
          5. ????cstmt.setString(1,?"1");??
          6. ????cstmt.registerOutParameter(2,?java.sql.Types.VARCHAR);??
          7. ????cstmt.executeUpdate();??
          8. ????cstmtControl.setReturnValue(1);??
          9. ????cstmt.getString(2);??
          10. ????cstmtControl.setReturnValue("5,4,3");??
          11. ????cstmt.close();??
          12. ????cstmtControl.replay();??
          13. ??????
          14. ??????
          15. ????String?rusult?=?dao.getNumber();??
          16. ????Assert.assertEquals("5,4,3",?rusult);??
          17. ??????
          18. ????conControl.verify();??
          19. ????cstmtControl.verify();??

          oh,my got!測(cè)試代碼比實(shí)現(xiàn)代碼還要多。這段代碼能執(zhí)行嗎?
          我想可以的。easymock的原理是記錄-回放的模式。
          我想要做的工作是:
          1,記錄你mock對(duì)象的工作記錄,比如上面的代碼我們mock對(duì)象的工作記錄是:
          java 代碼
          1. conn.prepareCall("{call?LUCK_LOAD_COMMON(?,?)}");??
          2. ????????conControl.setReturnValue(cstmt);??
          3. ????????cstmt.setString(1,?"1");??
          4. ????????cstmt.registerOutParameter(2,?java.sql.Types.VARCHAR);??
          5. ????????cstmt.executeUpdate();??
          6. ????????cstmtControl.setReturnValue(1);??
          7. ????????cstmt.getString(2);??
          8. ????????cstmtControl.setReturnValue("5,4,3");??
          9. ????????cstmt.close();??
          10. ??

          ?如果你工作記錄的代碼要求有返回值的話,那么你必須提供一個(gè)自定義的值給它,否則會(huì)報(bào)錯(cuò)。比如上面的
        1. ?cstmt.getString(2);??
        2. ????????cstmtControl.setReturnValue("5,4,3");?? //自己定義的返回值,用作以后的比較。
          上面的是記錄操作,回放的時(shí)候,easymock會(huì)把記錄的操作跟你實(shí)際的代碼進(jìn)行比較,如果里面出了什么差錯(cuò),那么不好意思你的代碼有問(wèn)題,請(qǐng)修正后再測(cè)試。

          如果有興趣可以自己試下。


        3. 比如如果您
          conn.prepareCall("{call LUCK_LOAD_COMMON(?,?)}");
          修改為
          conn.prepareCall("{call LUCK_LOAD_COMMON(?,?,?)}");
          則出現(xiàn)的異常是:
          junit.framework.AssertionFailedError:
          Unexpected method call prepareCall("{call LUCK_LOAD_COMMON(?,?)}"):
          prepareCall("{call LUCK_LOAD_COMMON(?,?)}"): expected: 0, actual: 1
          prepareCall("{call LUCK_LOAD_COMMON(?,?,?)}"): expected: 1, actual: 0

          現(xiàn)在我總算是對(duì)ribbon說(shuō)對(duì)于數(shù)據(jù)庫(kù)的測(cè)試還是真實(shí)環(huán)境的好。
          因?yàn)槟銣y(cè)試的時(shí)候你不知道存儲(chǔ)過(guò)程是否正確。
          而且如果用真實(shí)的數(shù)據(jù)庫(kù)測(cè)試,相對(duì)與mock測(cè)試,則簡(jiǎn)潔很多。而且清晰很多。
          上面只是在比較少邏輯的時(shí)候測(cè)試,如果代碼邏輯復(fù)雜,我覺(jué)得寫(xiě)出來(lái)的測(cè)試代碼會(huì)更復(fù)雜,這有引出,可能維護(hù)測(cè)試代碼的工作比維護(hù)代碼的工作更累



          爬蟲(chóng)工作室 -- 專(zhuān)業(yè)的手機(jī)軟件開(kāi)發(fā)工作室
          3G視線 -- 專(zhuān)注手機(jī)軟件開(kāi)發(fā)
          posted on 2007-03-21 13:29 3G工作室 閱讀(1544) 評(píng)論(2)  編輯  收藏 所屬分類(lèi): 單元測(cè)試

          Feedback

          # re: 用easymock測(cè)試jdbc 2007-03-22 11:56 mars
          最近才開(kāi)始了解tdd,不過(guò)看你的代碼不太明白,你并不是要測(cè)試easymock而是要測(cè)試你的邏輯,因此你因該是你的業(yè)務(wù)代碼盡可能的獨(dú)立與第三方的api(這也是依賴注入和依賴查找之間的區(qū)別),這樣才好mock,另外,使用數(shù)據(jù)庫(kù)測(cè)試所面臨的問(wèn)題更多.  回復(fù)  更多評(píng)論
            

          # re: 用easymock測(cè)試jdbc 2007-03-22 12:03 爬蟲(chóng)工作室
          本來(lái)就不是去測(cè)試easymock。
          只是借助這個(gè)工具去測(cè)試我們的業(yè)務(wù)邏輯
          至于easymock邏輯是否正確,就不是我們要做的事情  回復(fù)  更多評(píng)論
            


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 卢龙县| 沽源县| 黔南| 大同市| 工布江达县| 周至县| 山阴县| 宜兰县| 承德县| 泾川县| 织金县| 榕江县| 淮阳县| 大关县| 遂川县| 穆棱市| 延庆县| 广汉市| 磐安县| 平顺县| 油尖旺区| 金沙县| 大石桥市| 兴宁市| 醴陵市| 山丹县| 铜陵市| 翁源县| 皋兰县| 伊金霍洛旗| 仪陇县| 西吉县| 阿拉尔市| 肥乡县| 建德市| 莆田市| 灌云县| 蚌埠市| 法库县| 碌曲县| 修文县|