iOS开发之模拟接口假数据

发布时间: 2018-04-09

一、前言

我们在iOS开发的过程中,往往后端和前端都是并行的,当后端的接口没有完善的时候就会影响到我们的开发,而我也在我编程的过程中也经历过很多方法去制造假数据,下面我就一一说一下吧。

二、方法

下面我们以如下的JSON字段进行一下说明

{
  "code": 0,
  "message": "成功",
  "data": {
    "website":"https://www.ianisme.com",
    "list": [
      {
        "day": "30",
        "month": "10",
        "year": "2017"
      }
    ]
  }
}

2.1 Dictionary假数据

这种方法应该说是最不建议使用的方法了。假设我们工程中使用的是JSModel进行Model层转换的。
我们需要这样写一个NSDictionary

如图所示我们就可以这样去写假数据了。这种方法是每次都要去修改和编辑大量代码,并且关于网络请求的代码还测试不了,不推荐使用。

2.2 搭建后台假数据

我们可以本地用搭建一个网站环境或者使用远程服务器去请求。
我会保存一个json文件,然后用一个php文件去调用。

<?php

header("Content-type: text/html; charset=utf-8");
$test <span>=</span> $_POST["s"];
$json_string <span>=</span> <span>file_get_contents</span><span>(</span>$test . '.json');
echo $json_string;

这种情况下,我们可以直接把app端的网络请求代码全部写好,就相当于模仿后台的接口一样,到时候切换后台接口我们只需要更换下接口地址就行了。

2.3 APP端修改服务器数据

这里我们以 AFNetworking2.x 为例使用 NSURLProtocol 拦截 HTTP 请求。
创建NSURLProtocol的一个子类,重写里面的startLoading方法。

- (void)startLoading
{

NSMutableURLRequest <span>*</span>mutableReqeust <span>=</span> <span>[</span><span>[</span><span>self</span> request<span>]</span> mutableCopy<span>]</span><span>;</span>

<span>[</span>NSURLProtocol setProperty<span>:</span><span>@</span>YES forKey<span>:</span>hasInitKey inRequest<span>:</span>mutableReqeust<span>]</span><span>;</span>

<span>if</span> <span>(</span><span>[</span>mutableReqeust<span>.</span>URL<span>.</span>description containsString<span>:</span><span>@"api.ianisme.com"</span><span>]</span><span>)</span> <span>{</span>

    NSDictionary <span>*</span>dic <span>=</span> <span>@</span><span>{</span>
                          <span>@"code"</span><span>:</span> <span>@</span><span>0</span><span>,</span>
                          <span>@"message"</span><span>:</span> <span>@"成功"</span><span>,</span>
                          <span>@"data"</span><span>:</span> <span>@</span><span>{</span>
                                  <span>@"website"</span><span>:</span> <span>@"https://www.ianisme.com"</span><span>,</span>
                                  <span>@"list"</span><span>:</span> <span>@</span><span>[</span>
                                          <span>@</span><span>{</span>
                                              <span>@"day"</span><span>:</span> <span>@"30"</span><span>,</span>
                                              <span>@"month"</span><span>:</span> <span>@"10"</span><span>,</span>
                                              <span>@"year"</span><span>:</span> <span>@"2017"</span>
                                              <span>}</span>
                                          <span>]</span>
                                  <span>}</span>
                          <span>}</span><span>;</span>
    NSData <span>*</span>tempData <span>=</span> <span>[</span><span>self</span> toJSONData<span>:</span>dic<span>]</span><span>;</span>
    NSString <span>*</span>jsonString <span>=</span> <span>[</span><span>[</span>NSString alloc<span>]</span> initWithData<span>:</span>tempData
                                                 encoding<span>:</span>NSUTF8StringEncoding<span>]</span><span>;</span>

    NSData <span>*</span>data <span>=</span> <span>[</span>jsonString dataUsingEncoding<span>:</span>NSUTF8StringEncoding<span>]</span><span>;</span>

    NSURLResponse <span>*</span>response <span>=</span> <span>[</span><span>[</span>NSURLResponse alloc<span>]</span> initWithURL<span>:</span>mutableReqeust<span>.</span>URL
                                                        MIMEType<span>:</span><span>@"text/html"</span>
                                           expectedContentLength<span>:</span>data<span>.</span>length
                                                textEncodingName<span>:</span>nil<span>]</span><span>;</span>
    <span>[</span><span>self</span><span>.</span>client URLProtocol<span>:</span><span>self</span>
          didReceiveResponse<span>:</span>response
          cacheStoragePolicy<span>:</span>NSURLCacheStorageNotAllowed<span>]</span><span>;</span>

    <span>[</span><span>self</span><span>.</span>client URLProtocol<span>:</span><span>self</span> didLoadData<span>:</span>data<span>]</span><span>;</span>
    <span>[</span><span>self</span><span>.</span>client URLProtocolDidFinishLoading<span>:</span><span>self</span><span>]</span><span>;</span>

<span>}</span>
<span>else</span> <span>{</span>
    <span>self</span><span>.</span>myConnection <span>=</span> <span>[</span>NSURLConnection connectionWithRequest<span>:</span>mutableReqeust delegate<span>:</span><span>self</span><span>]</span><span>;</span>
<span>}</span>

}

此方法我们可以把相关网络请求写好,然后本地代码拦截后台的网络请求,用假数据修改就行了。以上只是一个原理的演示,实际开发,推荐使用强大的开源库OHHTTPStubs, 他可以伪造的网络数据和模拟的缓慢网络来进行调试。
传送门->OHHTTPStubs

2.4 代理拦截网络请求

这个是我比较推荐的一个方案,不需要修改app端代码。一切无损对接后台。

这就是利用代理软件的 Map Local 功能,将请求转换为请求电脑本地的静态json文件。

我们以Charles为例,我们把本地的接口写好之后,我们使用Charles抓一下这个接口的请求,此时肯定是失败的。

如图:

我们去 Map Local 指向电脑中的一个json文件。

如图:


这样我们就将此接口指向了电脑本地的一个json文件,我们可以用此方法,将所有的接口都分别指向本地的各自的 json 文件,当后台接口完毕后,我们就可以关闭 Map Local 无缝衔接到真正的后台。

本文涉及到的部分代码 -> 点我下载

三、总结

以上四个方法,我的推荐程度是由小到大的。我认为最好不要去动APP的代码,所以我推荐第四种,赶快去尝试一下吧!你用的哪种呢?欢迎留言交流。

参考与延伸:

《iOS 开发中使用 NSURLProtocol 拦截 HTTP 请求》

《如何进行 HTTP Mock(iOS)》

《Charles 从入门到精通》

《关于Charles抓HTTPS包的tips》

《iOS单元测试:Specta + Expecta + OCMock + OHHTTPStubs + KIF》

请在下方留下您的评论.加入TG吹水群