Sky's blog

          我和我追逐的夢

          常用鏈接

          統計

          其他鏈接

          友情鏈接

          最新評論

          easymock教程-運行時返回值或者異常

                  前面的教程中,我們看到easymock可以通過expect方法來設定mock方法的返回值或者異常,但是注意這些案例中設置的返回值都是在調用被測試的類的方法前就已經確定下來的,即我們其實在測試類的代碼運行前(實際是在EasyMock.replay()方法調用前)就已經"預知"了返回結果。

              但是在某些情況下,我們可能無法預知返回值,比如我們需要根據輸入的參數值來決定返回什么,而這個參數可能無法在record階段獲得。因此在mock方法中我們無法在record階段就決定應該返回什么。

              對于這種場景,easymock提供了IAnswer接口和andAnswer()方法來提供運行時決定返回值或者異常的機制。

              我們來看一個簡單的例子:

              public class Business {
                  
          private Service service;

                  
          public void execute() {
                      
          int count = ramdonInt();
                      
          int result = service.execute(count);
                  }


                  
          public void setService(Service service) {
                      
          this.service = service;
                  }


                  
          private int ramdonInt() {
                      Random random 
          = new Random();
                      
          return random.nextInt() / 10000;
                  }

              }


              
          public interface Service {
                  
          public int execute(int count);
              }

              在Business的execute()方法中,需要調用service.execute(int count)方法,而傳入的參數count是需要運行時才能確定的,這里為了簡單我們random了一個int來模擬這種情況。

              然后看測試案例

              @Test
              
          public void testRuntimeReturn() {
                  Business business 
          = new Business();
                  Service service 
          = EasyMock.createMock(Service.class);
                  business.setService(service);
                  EasyMock.expect(service.execute(EasyMock.anyInt())).andAnswer(
          new IAnswer<Integer>() {
                      
          public Integer answer() throws Throwable {
                          Integer count 
          = (Integer) EasyMock.getCurrentArguments()[0];
                          
          return count * 2;
                      }

                  }
          );

                  EasyMock.replay(service);
                  business.execute();
                  EasyMock.verify(service);
              }

              這里我們通過EasyMock.expect(service.execute(EasyMock.anyInt()))來接受任意值的count參數輸入,andAnswer(new IAnswer<Integer>() {}) 讓我們可以指定一個IAnswer的實現類來給出返回值。在這個IAnswer的實現類中,我們通過EasyMock.getCurrentArguments()[0]獲取到service.execute()方法的第一個參數,然后簡單的運用count*2規則給出返回值。這里的EasyMock.getCurrentArguments()方法可以獲取到運行時的參數列表,不過注意這個方法對重構不夠友好,如果參數列表發生變化則必須手工修改對象的獲取參數的代碼。

              下面是一個運行時拋出異常的例子,簡單起見我們通過設置exception的message來在錯誤信息中傳遞運行時的count值。

             @Test
              
          public void testRuntimeException() {
                  Business business 
          = new Business();
                  Service service 
          = EasyMock.createMock(Service.class);
                  business.setService(service);
                  EasyMock.expect(service.execute(EasyMock.anyInt())).andAnswer(
          new IAnswer<Integer>() {
                      
          public Integer answer() throws Throwable {
                          Integer count 
          = (Integer) EasyMock.getCurrentArguments()[0];
                          
          throw new RuntimeException("count=" + count);
                      }

                  }
          );

                  EasyMock.replay(service);
                  
          try {
                      business.execute();
                      fail(
          "should throw RuntimeException");
                  }
           catch (RuntimeException e) {
                      assertTrue(e.getMessage().indexOf(
          "count="!= -1);
                      
          //get count from message
                      EasyMock.verify(service);
                  }

              }

              除了IAnswer接口外,easymock中還有另外一個方式可以完成類似的功能,就是使用andDelegate()方法,

              public class ServiceStub implements Service {
                  
          public int execute(int count) {
                      
          return count * 2;
                  }

              }


              @Test
              
          public void testRuntimeReturn() {
                  Business business 
          = new Business();
                  Service service 
          = EasyMock.createMock(Service.class);
                  business.setService(service);
                  EasyMock.expect(service.execute(EasyMock.anyInt())).andDelegateTo(
          new ServiceStub());

                  EasyMock.replay(service);
                  business.execute();
                  EasyMock.verify(service);
              }

              這里需要先創建一個Service類的實現類和一個實例,然后通過andDelegateTo()將這個stub的實例傳進去,注意這里delegate進去的實例必須是mock對象接口相同。

              delegateTo方式實際上是我們手工創建了stub(mock和stub的概念及差別請參考本教程的"mock和stub"一文),這和我們使用easymock的初衷有所違背。而且當這個接口有眾多方法時,創建這樣一個stub會顯得很痛苦,不如使用IAnswer方便直接。

          posted on 2010-11-30 16:36 sky ao 閱讀(3604) 評論(0)  編輯  收藏 所屬分類: software test

          主站蜘蛛池模板: 佛冈县| 上高县| 昭通市| 武威市| 道真| 花垣县| 吐鲁番市| 桐柏县| 甘德县| 如皋市| 无棣县| 百色市| 阳原县| 长泰县| 华蓥市| 富民县| 昆明市| 洛扎县| 兴仁县| 尼木县| 湘潭县| 天峨县| 江山市| 宝清县| 柞水县| 防城港市| 宜丰县| 金湖县| 桃园市| 南召县| 响水县| 德江县| 永春县| 民勤县| 光泽县| 神农架林区| 庄河市| 文成县| 沙坪坝区| 新源县| 南昌县|