隨筆 - 23  文章 - 11  trackbacks - 0
          <2008年4月>
          303112345
          6789101112
          13141516171819
          20212223242526
          27282930123
          45678910

          常用鏈接

          留言簿(3)

          隨筆分類

          隨筆檔案

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

                單元測(cè)試應(yīng)該是簡(jiǎn)單和直觀的,而現(xiàn)實(shí)中的項(xiàng)目大多都是采用多層方式的,如EJB和hibernate的數(shù)據(jù)驅(qū)動(dòng)層的中間件技術(shù)。

                unitils來(lái)源于一個(gè)嘗試,就是希望能以更務(wù)實(shí)的方式來(lái)看待單元測(cè)試......

                這個(gè)指南會(huì)告訴你,什么項(xiàng)目可以使用unitils。 并在這個(gè)指導(dǎo)方針頁(yè) 中你可以了解到測(cè)試的準(zhǔn)側(cè)和它的特點(diǎn)。如果您想了解如何可以配置unitils ,并得以迅速地啟動(dòng),請(qǐng)查看cookbook

          • unitils的斷言
          • unitils的模塊
          • 數(shù)據(jù)庫(kù)的測(cè)試
          • 數(shù)據(jù)庫(kù)的自動(dòng)測(cè)試
          • hibernate的測(cè)試
          • jpa的測(cè)試
          • spring的測(cè)試
          • mock object的測(cè)試
          • 今后的方向

                unitils的斷言

                在開始這個(gè)指南之前我們先說(shuō)明一下獨(dú)立于unitils核心模塊的斷言。在下面的例子中,不需要進(jìn)行配置,將unitils的jar包和依賴包放在你的classpath下,就可以進(jìn)行測(cè)試了。

                通過(guò)反射進(jìn)行斷言

                一個(gè)典型的單元測(cè)試包含了結(jié)果值和期望值的比較,unitils提供了斷言的方法以幫助你進(jìn)行該操作,讓我們看看實(shí)例2中對(duì)有著id、first name、last name屬性的User類的2個(gè)實(shí)例的比較

          public class User {
              private long id;
              private String first;
              private String last;
          
              public User(long id, String first, String last) {
                  this.id = id;
                  this.first = first;
                  this.last = last;
              }
          }
          
          User user1 = new User(1, "John", "Doe");
          User user2 = new User(1, "John", "Doe");
          assertEquals(user1, user2);
              你期望這個(gè)斷言是成功的,因?yàn)檫@兩個(gè)實(shí)例含有相同的屬性,但是運(yùn)行的結(jié)果并非如此,應(yīng)為User類并沒有覆寫
          equals()方法,所以assertEquals是對(duì)兩個(gè)實(shí)例是否相等進(jìn)行判斷(user1 == user2)結(jié)果導(dǎo)致了比較的失敗。
              假設(shè)你像如下代碼一樣實(shí)現(xiàn)了equals方法
          public boolean equals(Object object) {
              if (object instanceof User) {
                  return id == ((User) object).id;
              }
              return false;
          }

                 這在你的程序邏輯中是一個(gè)合乎邏輯的實(shí)現(xiàn),當(dāng)兩個(gè)User實(shí)例擁有相同的id的時(shí)候,那么這兩個(gè)實(shí)例就是相等的。然而這種方式在你的單元測(cè)試中并不合適,并不能通過(guò)id的相同來(lái)認(rèn)為兩個(gè)user是相同的。

          User user1 = new User(1, "John", "Doe");
          User user2 = new User(1, "Jane", "Smith");
          assertEquals(user1, user2);

                 這個(gè)斷言將會(huì)成功,但這并不是你所期望的,因此不要使用assertEquals來(lái)對(duì)兩個(gè)對(duì)象進(jìn)行判定是否相等(外覆類和java.lang.String類除外)。要想斷言他們相等,一種方法就是斷言每個(gè)屬性相等。

          User user1 = new User(1, "John", "Doe");
          User user2 = new User(1, "John", "Doe");
          assertEquals(user1.getId(), user2.getId());
          assertEquals(user1.getFirst(), user2.getFirst());
          assertEquals(user1.getLast(), user2.getLast());

                 unitils提供了一些方法來(lái)幫助你執(zhí)行斷言更加的簡(jiǎn)單,通過(guò)反射,使用ReflectionAssert.assertRefEquals上面的代碼重寫如下:

          User user1 = new User(1, "John", "Doe");
          User user2 = new User(1, "John", "Doe");
          assertRefEquals(user1, user2);
             這個(gè)斷言將通過(guò)反射對(duì)兩個(gè)實(shí)例中的每個(gè)屬性都進(jìn)行比較,先是id、然后是first name、最后是last name。
             如果一個(gè)屬性本身也是一個(gè)對(duì)象,那么將會(huì)使用反射進(jìn)行遞歸比較,這同樣適合與集合、map、和數(shù)組之間的比較,他們
          的每個(gè)元素會(huì)通過(guò)反射進(jìn)行比較。如果值是一個(gè)基本類型或者是一個(gè)外覆類,那么將會(huì)使用==進(jìn)行值的比較,因此下面的斷
          言會(huì)取得成功
          assertRefEquals(1, 1L); 
          
          List<Double> myList = new ArrayList<Double>();
          myList.add(1.0);
          myList.add(2.0);
          assertRefEquals(Arrays.asList(1, 2), myList);

                寬松的斷言

               出于可維護(hù)性,這一點(diǎn)是十分重要的,舉例說(shuō)明:如果你要計(jì)算一個(gè)帳戶的余額,那你就沒比較檢查這個(gè)帳戶的名稱。他只會(huì)增加復(fù)雜性,使之更難理解。如果你想讓你的測(cè)試代碼更容易生存,更容易重構(gòu)的話,那請(qǐng)確保你斷言的范圍。

                寬松的順序

                在比較集合和數(shù)組的時(shí)候你可能并不關(guān)心他們中元素的順序,通過(guò)使用ReflectionAssert.assertRefEquals方法并配合ReflectionComparatorMode.LENIENT_ORDER參數(shù)將忽略元素的順序。

          List<Integer> myList = Arrays.asList(3, 2, 1);
          assertRefEquals(Arrays.asList(1, 2, 3), myList, LENIENT_ORDER);
             無(wú)視默認(rèn)
             第二種的從寬方式是使用ReflectionComparatorMode.IGNORE_DEFAULTS模式,當(dāng)這種模式被設(shè)置的時(shí)候,java
          的默認(rèn)值,如null、0、false將會(huì)不參與斷言(忽略)。
             舉個(gè)例子,如果你有一個(gè)User類,該類有著first name,last name,street等屬性,但是你僅僅想對(duì)first name
          和street進(jìn)行檢查而忽略其他的屬性。
          User actualUser   = new User("John", "Doe", new Address("First street", "12", "Brussels"));
          User expectedUser = new User("John",  null, new Address("First street", null,       null));
          assertRefEquals(expectedUser, actualUser, IGNORE_DEFAULTS);

                你所期望忽略的屬性的對(duì)象必須放在斷言左邊,如果放在右邊那么依然進(jìn)行比較。

          assertRefEquals(null, anyObject, IGNORE_DEFAULTS);  // Succeeds
          assertRefEquals(anyObject, null, IGNORE_DEFAULTS);  // Fails

                寬松的日期

                第三種從寬處理是ReflectionComparatorMode.LENIENT_DATES,當(dāng)兩個(gè)日期都是值,或者都是null的時(shí)候,實(shí)際的日期將會(huì)被忽略(即斷言為相等)。

          Date actualDate =   new Date(44444);
          Date expectedDate = new Date();
          assertRefEquals(expectedDate, actualDate, LENIENT_DATES);

                assertLenEquals

                ReflectionAssert還提供了一種斷言,他提供寬松的順序又提供無(wú)視的忽略。

          List<Integer> myList = Arrays.asList(3, 2, 1);
          assertLenEquals(Arrays.asList(1, 2, 3), myList); 
          
          assertLenEquals(null, "any");  // Succeeds
          assertLenEquals("any", null);  // Fails

                屬性斷言

                assertLenEqualsassertRefEquals都是比較對(duì)象,ReflectionAssert也提供方法對(duì)對(duì)象的屬性進(jìn)行比較。(依賴與ONGL)。

                一些屬性比較的例子

          assertPropertyLenEquals("id", 1, user);  //斷言u(píng)ser的id屬性的值是1 
          assertPropertyLenEquals("address.street", "First street", user); //斷言u(píng)ser的address的street屬性

                在這個(gè)方式中你期望的值和判定的對(duì)象也可以使用集合

          assertPropertyLenEquals("id", Arrays.asList(1, 2, 3), users);
          assertPropertyLenEquals("address.street", Arrays.asList("First street", 
          "Second street", "Third street"), users);
          posted on 2008-04-05 14:23 小小~咖啡豆 閱讀(2326) 評(píng)論(5)  編輯  收藏 所屬分類: 測(cè)試

          FeedBack:
          # re: Unitils開發(fā)指南(一) 2009-04-14 16:42 skyme
          assertRefEquals()這個(gè)方法好像是有問題的:
          我調(diào)試的時(shí)候用ReflectionAssert.assertRefEquals(user1, user2);

          import org.unitils.reflectionassert.*;
          import org.unitils.reflectionassert.ReflectionAssert;
          public void testUser(){
          User user1=new User(1,"John","Doe");
          User user2=new User(1,"John","Doe");
          ReflectionAssert.assertRefEquals(user1, user2);
          }
          測(cè)試是不通過(guò)的!
          如果我不要ReflectionAssert;那么報(bào)錯(cuò)
          按上面的代碼測(cè)試,測(cè)試不通過(guò)。好像這個(gè)反射是不是有問題啊!  回復(fù)  更多評(píng)論
            
          # re: Unitils開發(fā)指南(一) 2009-04-14 21:39 wangzhouyu
          有驗(yàn)證通過(guò)呀,@skyme
            回復(fù)  更多評(píng)論
            
          # re: Unitils開發(fā)指南(一) 2009-04-15 09:03 skyme
          使用Myeclipse6.0嗎? 我在看看我的測(cè)試環(huán)境JUnit3還是JUnit4
          我用的是Unitils2.2.jar包  回復(fù)  更多評(píng)論
            
          # re: Unitils開發(fā)指南(一) 2009-04-15 09:37 skyme
          請(qǐng)問下能不能告訴我你的msn,我的msn是:jiangduxi@yahoo.com.cn!
          想向你請(qǐng)教下! 謝謝  回復(fù)  更多評(píng)論
            
          # re: Unitils開發(fā)指南(一) 2009-04-15 10:17 wangzhouyu
          wzywjy@hotmail.com
            回復(fù)  更多評(píng)論
            

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


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 民县| 峨眉山市| 铅山县| 禄劝| 出国| 松阳县| 平山县| 古丈县| 华亭县| 长阳| 青浦区| 扎赉特旗| 鹤岗市| 颍上县| 淮滨县| 九江市| 乐安县| 柳林县| 长子县| 耿马| 长寿区| 新化县| 海伦市| 平利县| 台山市| 金坛市| 普兰店市| 秀山| 肇庆市| 天水市| 武义县| 大城县| 从化市| 轮台县| 长丰县| 乐安县| 咸丰县| 赤水市| 昌吉市| 麦盖提县| 收藏|