OKhttp Mock 服务返回数据

背景

在我们经常开发的时候,通常我们都会把时间花费在接口联调和等待接口阶段。作为开发人员我应该自己做出单元测试,但是这并不是我今天要描述的范围,今天我只要是以在后台接口还没有开发完成的阶段,协调测试先给出数据的响应格式,从而开发人员自己Mock 数据。以此,开发接下的流程。的确,在前一两年我还是自己搭建Tomcat 然后在自己的本地服务器存放自己需要Mock 解析的Json 文件。以此达到这样的目的,但是这样是存在一个问题,那就是接口的入参,在此就需要作出校验,很显然我们对这样的方式,表示不认同。所以,有了以下的内容。

简介

由于项目的网络框架是使用的是Retrofit+RxJava从而在实现上,有很大的便利。需要注意的是Retrofit是对于Okhttp 的再优化和封装。看到Okhttp 有没有想到什么。对的他有很强大的功能那就是Interceptor(拦截器)。

我们需要了解一下的几点:

Interceptor

OkHttp 可在 Request 和 Response 中设置任意个数的 Intercepor。对请求体和响应体进行处理。借助 OkHttp Interceptor 机制,创建一个 MockIntercepor,模拟返回一个 Response。当然他不只可以在Request、Response设置拦截,并且还可以设置网络状态的拦截、Header、等等。不在一一的赘述。如果你还不是足够的了解他的原理和使用方式,你可以观看一下的介绍https://github.com/square/okhttp/wiki/Interceptors

1. HeaderInterceptor

统一配置请求头,无需直接在业务封装层进行相关配置。减少代码的耦合性。

 /**
   * 设置请求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", "公司名称/应用名称")
                  .build();
          Request newRequest = builder.build();
  
          return chain.proceed(newRequest);
      }
  
      /**
       * Request Header
       * <p> 由于sign 与 URL 关联因此,它可理解为动态的参数,而不能理解为固定参数</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 数据的时候,其实是直接跳过请求参数的配置,也就是说我们需要拦截Resphone 进行拦截。如果你使用了RxJava 操作符的类型转义,这时候你就需要在gradle 中配置在Debug 状态下不在配置RxJavaCallAdapterFactory。因为我只是在Debug状态下进行Mock 数据,所以在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;
      }
  
  
      /**
       * 该方法是为动态的配置各个接口数据,为此,需要对各个接口的注解,进行
       * 拦截处理,以实现加载不同的json数据
       * @param chain
       * @return
       */
      private String createResponseBody(Chain chain) {
          String responseString = null;
          HttpUrl httpUrl = chain.request().url();
          String urlPath = httpUrl.url().toString();
  
          //url 匹配形式进行数据返回
   //      if (urlPath.matches("^(/users/)+[^/]+(/login)$")) {//匹配/users/{username}/login
  //            responseString = getResponseString("users_login.json");
  //        } else if (urlPath.matches("^(/users/)+[^/]*+$")) {//匹配/users/{username}
  //            responseString = getResponseString("test.json");
  //        }
          // 直接使用文件进行数据返回,不提倡。没有针对性
          return FileUtils.testCase;
      }
  
      private String getResponseString(String fileName) {
          return FileUtils.readFile(responeJsonPath +fileName,"UTF-8");
      }
  }

当然使用这样的方式不仅能够实现这样两种的配置。我们进行网络的访问的时候通常会携带一些固定的参数,如version、os、platform 等,我们也可以针对固定参数的一些配置同样适用。再次就不在过多的赘述了。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 228,030评论 6 531
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 98,310评论 3 415
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 175,951评论 0 373
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 62,796评论 1 309
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 71,566评论 6 407
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 55,055评论 1 322
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,142评论 3 440
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,303评论 0 288
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 48,799评论 1 333
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 40,683评论 3 354
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 42,899评论 1 369
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,409评论 5 358
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,135评论 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,520评论 0 26
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 35,757评论 1 282
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,528评论 3 390
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 47,844评论 2 372