OKhttp Mock 服務(wù)返回數(shù)據(jù)

背景

在我們經(jīng)常開發(fā)的時候,通常我們都會把時間花費在接口聯(lián)調(diào)和等待接口階段。作為開發(fā)人員我應(yīng)該自己做出單元測試,但是這并不是我今天要描述的范圍,今天我只要是以在后臺接口還沒有開發(fā)完成的階段,協(xié)調(diào)測試先給出數(shù)據(jù)的響應(yīng)格式,從而開發(fā)人員自己Mock 數(shù)據(jù)。以此,開發(fā)接下的流程。的確,在前一兩年我還是自己搭建Tomcat 然后在自己的本地服務(wù)器存放自己需要Mock 解析的Json 文件。以此達到這樣的目的,但是這樣是存在一個問題,那就是接口的入?yún)?,在此就需要作出校驗,很顯然我們對這樣的方式,表示不認同。所以,有了以下的內(nèi)容。

簡介

由于項目的網(wǎng)絡(luò)框架是使用的是Retrofit+RxJava從而在實現(xiàn)上,有很大的便利。需要注意的是Retrofit是對于Okhttp 的再優(yōu)化和封裝。看到Okhttp 有沒有想到什么。對的他有很強大的功能那就是Interceptor(攔截器)。

我們需要了解一下的幾點:

Interceptor

OkHttp 可在 Request 和 Response 中設(shè)置任意個數(shù)的 Intercepor。對請求體和響應(yīng)體進行處理。借助 OkHttp Interceptor 機制,創(chuàng)建一個 MockIntercepor,模擬返回一個 Response。當然他不只可以在Request、Response設(shè)置攔截,并且還可以設(shè)置網(wǎng)絡(luò)狀態(tài)的攔截、Header、等等。不在一一的贅述。如果你還不是足夠的了解他的原理和使用方式,你可以觀看一下的介紹https://github.com/square/okhttp/wiki/Interceptors

1. HeaderInterceptor

統(tǒng)一配置請求頭,無需直接在業(yè)務(wù)封裝層進行相關(guān)配置。減少代碼的耦合性。

 /**
   * 設(shè)置請求Header
   *
   */
  public class HeaderInterceptor implements Interceptor {
      @Override
      public Response intercept(Chain chain) throws IOException {
          Request request = chain.request();
          Request.Builder builder = request.newBuilder();
          builder.addHeader("-Header", creatHeader())
                  .addHeader("user-agent", "公司名稱/應(yīng)用名稱")
                  .build();
          Request newRequest = builder.build();
  
          return chain.proceed(newRequest);
      }
  
      /**
       * Request Header
       * <p> 由于sign 與 URL 關(guān)聯(lián)因此,它可理解為動態(tài)的參數(shù),而不能理解為固定參數(shù)</p>
       *
       * @return
       */
      public String creatHeader() {
          StringBuffer header = new StringBuffer();
          header.append("platform").append("=").append("android").append(";")
                  .append("os").append("=").append(Build.VERSION.SDK_INT).append(";")
                  .append("appid").append("=").append("com.xxx.xxx").append(";")
                  .append("version").append("=").append("2320").append(";")
                  .append("mid").append("=").append(Build.MODEL.replaceAll(" ", "_")).append(";")
                  .append("channel").append("=").append("ceshi");// 使用gradle 語法進行獲取不同的渠道配置
          return header.toString();
      }
  
  }

2. MockDataIntercepter

在這里可能需要解釋的是,因為我們在Mock 數(shù)據(jù)的時候,其實是直接跳過請求參數(shù)的配置,也就是說我們需要攔截Resphone 進行攔截。如果你使用了RxJava 操作符的類型轉(zhuǎn)義,這時候你就需要在gradle 中配置在Debug 狀態(tài)下不在配置RxJavaCallAdapterFactory。因為我只是在Debug狀態(tài)下進行Mock 數(shù)據(jù),所以在gradle 文件中配置變量,使其注入到BuildConfig 類型當中。已提供給項目全局使用,retrofitBuilder.addCallAdapterFactory(RxJavaCallAdapterFactory.create()); 具體配置如下:

public class MockDataIntercepter implements Interceptor {
      private final String responeJsonPath;
  
      public MockDataIntercepter(String responeJsonPath) {
          this.responeJsonPath = responeJsonPath;
      }
      @Override
      public Response intercept(Chain chain) throws IOException {
          String responseString = createResponseBody(chain);
          //Response 配置
          Response response = new Response.Builder()
                  .code(200)
                  .message(responseString)
                  .request(chain.request())
                  .protocol(Protocol.HTTP_1_0)
                  .body(ResponseBody.create(MediaType.parse("application/json"), responseString.getBytes()))
                  .addHeader("content-type", "application/json")
                  .build();
          return response;
      }
  
  
      /**
       * 該方法是為動態(tài)的配置各個接口數(shù)據(jù),為此,需要對各個接口的注解,進行
       * 攔截處理,以實現(xiàn)加載不同的json數(shù)據(jù)
       * @param chain
       * @return
       */
      private String createResponseBody(Chain chain) {
          String responseString = null;
          HttpUrl httpUrl = chain.request().url();
          String urlPath = httpUrl.url().toString();
  
          //url 匹配形式進行數(shù)據(jù)返回
   //      if (urlPath.matches("^(/users/)+[^/]+(/login)$")) {//匹配/users/{username}/login
  //            responseString = getResponseString("users_login.json");
  //        } else if (urlPath.matches("^(/users/)+[^/]*+$")) {//匹配/users/{username}
  //            responseString = getResponseString("test.json");
  //        }
          // 直接使用文件進行數(shù)據(jù)返回,不提倡。沒有針對性
          return FileUtils.testCase;
      }
  
      private String getResponseString(String fileName) {
          return FileUtils.readFile(responeJsonPath +fileName,"UTF-8");
      }
  }

當然使用這樣的方式不僅能夠?qū)崿F(xiàn)這樣兩種的配置。我們進行網(wǎng)絡(luò)的訪問的時候通常會攜帶一些固定的參數(shù),如version、os、platform 等,我們也可以針對固定參數(shù)的一些配置同樣適用。再次就不在過多的贅述了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容