• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • 企業系統集成點測試策略(4)

    發表于:2013-08-29來源:InfoQ作者:熊節點擊數: 標簽:集成測試
    對已有系統的重構 如果一開始就按照前文所述的模式來設計集成點,自然很容易保障系統的可測試性;但如果一開始沒有做好設計,沒有抽象出網絡端點的

      對已有系統的重構

      如果一開始就按照前文所述的模式來設計集成點,自然很容易保障系統的可測試性;但如果一開始沒有做好設計,沒有抽象出“網絡端點”的概念,而是把網絡訪問的邏輯與其他邏輯耦合在一起,自然也就難以寫出專門針對網絡訪問的測試,從而使得大量測試會發起真實的網絡訪問,使構建變得緩慢而不可靠。

      下面就是一段典型的代碼結構,其中雜糅了幾種不同的職責:準備請求正文;發起網絡請求;處理應答內容。

      PostMethod postMethod = getPostMethod(

      velocityContext, templateName, soapAction);

      new HttpClient().executeMethod(postMethod);

      String responseBodyAsString = postMethod.getResponseBodyAsString();

      if (responseBodyAsString.contains("faultstring")) {

      throw new WmbException();

      }

      Document document;

      try {

      LOGGER.info("request:\n" + responseBodyAsString);

      document = DocumentHelper.parseText(responseBodyAsString);

      } catch (Exception e) {

      throw new WmbParseException(

      e.getMessage() + "\nresponse:\n" + responseBodyAsString);

      }

      return document;

      針對每個要集成的服務方法,類似的代碼結構都會出現,從而出現了“重復代碼”的壞味道。由于準備請求正文、處理應答內容等邏輯各處不同(例如上面的代碼使用Velocity[10]來生成請求正文、使用JDOM[11]來解析應答),這里的重復并不那么直觀,自動化的代碼檢視工具(例如Sonar)通常也不能發現。因此第一步的重構是讓重復的結構浮現出來。

      使用抽取函數(Extract Method)、添加參數(Add Parameter)、刪除參數(Remove Parameter)等重構手法,我們可以把上述代碼整理成如下形狀:

      // 1. prepare request body

      String requestBody = renderTemplate(velocityContext, templateName);

      // 2. execute a post method and get back response body

      PostMethod postMethod = getPostMethod(soapAction, requestBody);

      new HttpClient().executeMethod(postMethod);

      String responseBody = postMethod.getResponseBodyAsString();

      if (responseBodyAsString.contains("faultstring")) {

      throw new WmbException();

      }

      // 3. deal with response body

      Document document = parseResponse(responseBody);

      return document;

      這時,第2段代碼(使用預先準備好的請求正文執行一個POST請求,并拿回應答正文)的重復就變得明顯了?!吨貥嫛穼@種情況做了介紹[12]:

      如果兩個毫不相關的類出現Duplicated Code,你應該考慮對其中一個使用Extract Class,將重復代碼提煉到一個獨立類中,然后在另一個類內使用這個新類。但是,重復代碼所在的函數也可能的確只應該屬于某個類,另一個類只能調用它,抑或這個函數可能屬于第三個類,而另兩個類應該引用這第三個類。你必須決定這個函數放在哪兒最合適,并確保它被安置后就不會再在其他任何地方出現。

      這正是我們面對的情況,也正是“網絡端點”這個概念應該出現的時候。使用抽取函數和抽取類(Extract Class)的重構手法,我們就能得到名為SOAPEndPoint的類:

      public class SOAPEndPoint {

      public String post(String soapAction, String requestBody) {

      PostMethod postMethod = getPostMethod(soapAction, requestBody);

      new HttpClient().executeMethod(postMethod);

      String responseBody = postMethod.getResponseBodyAsString();

      if (responseBodyAsString.contains("faultstring")) {

      throw new WmbException();

      }

      return responseBody;

      }

      原來的代碼變為使用這個新的類:

      // 1. prepare request body

      String requestBody = renderTemplate(velocityContext, templateName);

      // 2. execute a post method and get back response body

      // soapEndPoint is dependency injected by Spring Framework

      String responseBody = soapEndPoint.post(soapAction, requestBody);

      // 3. deal with response body

      Document document = parseResponse(responseBody);

      return document;

      再按照前文所述的測試策略,使用Moco給SOAPEndPoint類添加測試??梢钥吹?,SOAPEndPoint的邏輯相當簡單:把指定的請求文本POST到指定的URL;如果應答文本包含“faultstring”字符串,則拋出異常;否則直接返回應答文本。盡管名為 “SOAPEndPoint”,post這個方法其實根本不關心請求與應答是否符合SOAP協議,因此在測試這個方法時我們也不需要讓Moco返回符合 SOAP協議的應答文本,只要覆蓋應答中是否包含“faultstring”字符串的兩種情況即可。

      讀者或許會問:既然post方法并不介意請求與應答正文是否符合SOAP協議,為什么這個類叫SOAPEndPoint?答案是:在本文沒有給出實現代碼的getPostMethod方法中,我們需要填入一些HTTP頭信息,這些信息是與提供Web Services的被集成服務相關的。這些HTTP頭信息(例如應用程序的身份認證、Content-Type等)適用于所有服務方法,因此可以抽取到通用的getPostMethod方法中。

      隨后,我們可以編寫一些描述性的集成測試,并用mock的方式使所有“使用SOAPEndPoint的類”的測試不再發起網絡請求。至此,我們就完成了對已有的集成點的重構,并得到了一組符合前文所述的測試策略的測試用例。當然讀者可以繼續重構,將請求構造器與應答解析器也分離出來,在此不再贅述。

    原文轉自:http://www.infoq.com/cn/articles/enterprise-systems-integration-points

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>