熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java開源技術 >> 正文

關於Java單元測試中的偽對象介紹(圖)

2013-11-23 20:07:12  來源: Java開源技術 

  在單元測試的策略中偽對象被廣泛使用他從測試中分離了外部的不需要的因素並且幫助開發人員專注於被測試的功能
  
  EasyMock是一個在這方面很有名的工具可以在運行時為給定的接口創建偽對象偽對象的行為可以在測試用例中的執行測試代碼之前被定義EasyMock基於javalangreflectProxy他可以根據給定的接口創建動態代理類或者對象但因為使用Proxy使得他有一個天生的缺陷只能創建基於接口的偽對象
  
  Mocquer是一個類似的工具但他擴展了EasyMock的功能能夠支持創建類的偽對象
  
  Mocquer介紹
  
  Mocquer基於Dunamis項目被用來為特定的類或接口生成動態代理類或對象為方便使用他遵循EasyMock的類和方法的命名規范只是在內部使用不同的實現方法
  
  MockControl是Mocquer項目中最重要的類他被用來控制偽對象的生命周期和行為定義這個類中有四類方法
  
  生命周期控制方法
  
  ·public void replay();
  ·public void verify();
  ·public void reset();
  
  偽對象在他的生命周期中有三種狀態准備態工作態驗證態顯示了偽對象的生命周期
   
  Figure Mock object life cycle
  
  剛開始偽對象處於准備態他的表現行為可以在這裡定義replay()將改變偽對象的狀態為工作態在這個狀態中所有偽對象的方法調用將會遵循在准備態下定義的行為在verify()調用後偽對象就處於驗證態MockControl會比較偽對象的預定義行為與實際行為是否匹配匹配規則依賴於使用的MockControl類型這個會在稍後解釋開發人員可以在需要時調用replay()來重現預定義的行為而任何狀態下調用reset()將會清除狀態歷史並重置為初始的准備態
  
  工廠方法
  
  ·public static MockControl createNiceControl();
  ·public static MockControl createControl();
  ·public static MockControl createStrictControl();
  
  Mocquer提供了三種MockControl寬松的普通的和嚴格的開發人員可以在自己的測試用例中根據測試的內容(測試點)和測試的執行方式(測試策略)選擇相應的MockControl寬松的MockControl是最隨意的他不關心偽對象中方法調用的順序甚至未預期的方法調用只是返回一個缺省值(依賴於方法的返回值)普通的MockControl比寬松的MockControl嚴格些未預期的方法調用會導致AssertionFailedError異常嚴格的MockControl是最嚴格的如果偽對象在工作態下方法調用的順序與准備態的不同就會拋出AssertionFailedError異常下表顯示了三種不同MockControl的區別
  
  下面是每一個工廠方法的兩個不同版本
  public static MockControl createXXXControl(Class clazz); public static MockControl createXXXControl(Class clazz  Class[] argTypes Object[] args);
  
  如果類是作為接口來模擬的或者他有一個公共或保護的缺省構造函數則第一個版本的方法會被使用否則第二個版本會被用來定義標識和提供參數給期望的構造函數
  
  例如假設ClassWithNoDefaultConstructor是一個沒有缺省構造函數的類
  
  public class ClassWithNoDefaultConstructor {
  public ClassWithNoDefaultConstructor(int i) {
  
  }
  
  }
  
  ·偽對象獲取方法
  
  public Object getMock();
  
  每一個MockControl包含一個生成的偽對象的引用開發人員可以使用這個方法取得偽對象並且轉換為實際的對象類型
  
  //get mock control
  MockControl control = MockControlcreateControl(Fooclass);
  //Get the mock object from mock control
  Foo foo = (Foo) controlgetMock();
  
  ·行為定義方法
  
  public void setReturnValue( value);
  public void setThrowable(Throwable throwable);
  public void setVoidCallable();
  public void setDefaultReturnValue( value);
  public void setDefaultThrowable(Throwable throwable);
  public void setDefaultVoidCallable();
  public void setMatcher(ArgumentsMatcher matcher);
  public void setDefaultMatcher(ArgumentsMatcher matcher);
  
  MockControl允許開發人員定義偽對象的每一個方法的行為當他在准備態時開發人員可以調用偽對象的方法首先規定哪一個調用方法的行為需要被定義然後開發人員可以使用行為定義的方法之一來定義行為例如看一下下面的Foo類
  //Foojava
  public class Foo {
  public void dummy() throw ParseException {
  
  }   public String bar(int i) {
  
  }   public boolean isSame(String[] strs) {
  
  }   public void add(StringBuffer sb String s) {
  
  }
  }
  
  偽對象的行為可以按照下面的方式來定義
  
  //get mock control
  MockControl control = MockControlcreateControl(Fooclass);
  //get mock object
  Foo foo = (Foo)controlgetMock();
  //begin behavior definition
  //specify which method invocations behavior
  //to be defined
  foobar();
  //define the behavior return ok when the
  //argument is
  controlsetReturnValue(ok);
  
  //end behavior definition
  controlreplay();
  
  
  MockControl中超過個方法是行為定義方法他們可以如下分類
  
  o    setReturnValue()
  
  這些方法被用來定義最後的方法調用應該返回一個值作為參數這兒有個使用原始類型作業參數的`setReturnValue()方法如setReturnValue(int i)或setReturnValue(float f)setReturnValue(Object obj)被用來滿足那些需要對象作為參數的方法如果給定的值不匹配方法的返回值則拋出AssertionFailedError異常
  
  當然也可以在行為中加入預期調用的次數這稱為調用次數限制
  
  MockControl control =
  
  Foo foo = (Foo)controlgetMock();
  
  foobar();
  //define the behavior return ok when the
  //argument is And this method is expected
  //to be called just once
  setReturnValue(ok );
  
  
  上面的代碼段定義了bar()方法只能被調用一次如果提供一個范圍又會怎麼樣呢?
  
  foobar();
  //define the behavior return ok when the
  //argument is And this method is expected
  //to be called at least once and at most
  //times
  setReturnValue(ok );
  
  
  現在bar()被限制至少被調用一次最多更方便的是Range已經預定義了一些限制范圍
  
  foobar();
  //define the behavior return ok when the
  //argument is And this method is expected
  //to be called at least once
  setReturnValue(ok RangeONE_OR_MORE);
  
  
  RangeONE_OR_MORE是一個預定義的Range實例這意味著方法應該被調用至少一次如果setReturnValue()中沒有定義調用次數限制如setReturnValue(Hello)RangeONE_OR_MORE被認為是缺省值還有兩個預定義的Range實例RangeONE(就一次)和RangeZERO_OR_MORE(對調用次數沒有限制)
  
  這兒還有一個特定的設置返回值的方法setDefaultReturnValue()他將代替方法的參數值作為返回值缺省的調用次數限制為RangeONE_OR_MORE這被稱為方法參數值敏感性
  
  foobar();
  //define the behavior return ok when calling
  //bar(int) despite the argument value
  setDefaultReturnValue(ok);
  
  
  o    setThrowable
  
  setThrowable(Throwable throwable)被用來定義方法調用異常拋出的行為如果給定的throwable不匹配方法的異常定義則AssertionFailedError會被拋出調用次數的限制與方法參數值敏感性是一致的
  
  try {
  foodummy();
  } catch (Exception e) {
  //skip
  }
  //define the behavior throw ParseException
  //when call dummy() And this method is expected
  //to be called exactly once
  controlsetThrowable(new ParseException( ) );
  
  
  o    setVoidCallable()
  setVoidCallable()被用於沒有返回值的方法調用次數的限制與方法參數值敏感性是一致的
  
  try {
  foodummy();
  } catch (Exception e) {
  //skip
  }
  //define the behavior no return value
  //when calling dummy() And this method is expected
  //to be called at least once
  controlsetVoidCallable();
  
  
  o
From:http://tw.wingwit.com/Article/program/Java/ky/201311/27968.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.