美文网首页
Moco接口框架应用实战

Moco接口框架应用实战

作者: 零下的雨 | 来源:发表于2018-11-14 14:10 被阅读0次

    一、什么是Moco:
    Moco 是一个搭建模拟服务器的工具,其支持 API 和独立运行两种方式,前者通常是在 junit 、testng等测试框架中使用,后者则是通过运行一个 jar 包开启服务。

    二、Moco在开发中会起到的作用:
    Moco是针对HTTP集成而生的,不过,现在也有人把它用在其它需要一个模拟服务器的场景中。比如,在移动开发中,有人开发一个移动应用,需要有一个远端服务,但在开发时,这个服务还不存在,他就用Moco模拟了一个服务,保证移动应用可以顺利的开发。同样,也有人把它用在Web前端开发里,当我们的页面需要通过与服务器交互时,就可以用Moco模拟这样一个服务。这种做法在开发一个页面原型时,非常有用,因为那个时候,我们还来不及开发一个完整的服务。

    三、Moco在接口测试中的用处:
    既然开发人员可以通过 Moco 模拟一个还不存在的服务来进行开发、调试,那对于接口测试来说,也可以模拟一个服务进行测试。
    一般而言,在项目的接口文档输出后,开发人员会进行接口开发工作,测试人员会进行接口用例的设计,但往往完成用例设计会先于接口开发工作,此时如果要进行接口用例的执行,则前提是开发人员完成接口开发工作。
    而通过 Moco 框架,就可以在接口文档输出后,在接口开发、接口用例设计的同时,使用 Moco 搭建一个模拟服务器,这样在用例设计完成后,即使接口开发工作还未完成,也可以立即进行执行接口用例,在这个过程中可以修改、补充用例,如此的话,在接口开发完成以后,只需要简单的去执行所有的用例就 OK,省去了很大的工作量,并且这些完善的用例,用自动化去执行,效果更佳。

    四、Moco的应用:

    本章会通过示例讲如下信息:
    模拟get请求
    模拟带参数的get请求
    模拟post请求
    模拟带form格式参数的post请求
    模拟request请求中带cookies信息的get请求
    模拟request请求中带cookies的post请求,post请求带json格式参数,返回结果也使用json格式
    模拟response返回中带有cookies信息的get请求
    模拟带有headers信息的mock请求
    模拟有重定向的接口
    使用httpclient调moco的接口

       Moco jar下载地址:
    

    https://repo1.maven.org/maven2/com/github/dreamhead/moco-runner/0.11.0/
    下载红框中的内容:

    image.png

    把jar包放到项目根目录下:


    image.png

    新建一个json文件,文件名为startup1.json


    image.png

    json中内容为:

    [
      {
        "description": "这是第一个moco操作,格式要写正确,中括号、大括号一定要有,description是描述,request是请求,uri是请求路径,response是返回结果,text是返回的是文本类型内容",
        "request": {
          "uri": "/demo"
        },
        "response": {
          "text": "this is the first moco demo"
        }
      }
    ]
    

    格式一定要写对,中括号、大括号一定要有,description是描述,request是请求,uri是请求路径,response是返回结果,text是返回的是文本类型内容
    进入项目目录中,执行命令启动服务:


    image.png

    java -jar ./moco-runner-0.11.0-standalone.jar http -p 8888 -c startup1.json
    http:是指是http协议,-p 8888是端口号 -c是执行当前文件

    然后在postman中调接口执行就可以了,默认是get请求:


    image.png

    如果在text中写中文,会出现乱码情况,需要加配置信息:

      {"description":"这是第二个moco操作,模拟返回值为中文",
        "request":{
          "uri":"/demotwo"
        },
        "response":{
          "text":"这是第二个demo"
        }
    
      }
    

    在postman中调接口返回乱码:


    image.png

    在返回结果中加入:
    "headers":{
    "Content-Type":"text/html;charset=gbk"
    }

    {"description":"这是第二个moco操作,模拟返回值为中文",
        "request":{
          "uri":"/demotwo"
        },
        "response":{
          "text":"这是第二个demo",
          "headers":{
            "Content-Type":"text/html;charset=gbk"
          }
    
        }
    
      }
    

    修改json文件不需要重启,服务热部署会自动重启


    image.png

    在浏览器中调接口能成功返回中文:


    image.png

    为什么要在response中加一个header呢?
    是因为服务器要通过实体头(header)的形式告诉浏览器一些信息,Content-Type就是指服务器告诉浏览器它发送的数据属于什么文件类型。 "Content-Type":"text/html;charset=gbk"就是服务器告诉浏览器返回的内容是text/html格式要以html的格式展示,charset=gbk就是字符集,告诉浏览器可以解析中文字符信息。

    扩展一个小知识:
    gbk和utf8的区别
    我们这里将以最简单最容易理解的方式来描述GBK和UTF8的区别,以及它们分别是什么。

    GBK编码:是指中国的中文字符,其它它包含了简体中文与繁体中文字符,另外还有一种字符“gb2312”,这种字符仅能存储简体中文字符。

    UTF-8编码:它是一种全国家通过的一种编码,如果你的网站涉及到多个国家的语言,那么建议你选择UTF-8编码。

    GBK和UTF8有什么区别?

    UTF8编码格式很强大,支持所有国家的语言,正是因为它的强大,才会导致它占用的空间大小要比GBK大,对于网站打开速度而言,也是有一定影响的。

    GBK编码格式,它的功能少,仅限于中文字符,当然它所占用的空间大小会随着它的功能而减少,打开网页的速度比较快。

    本小节中使用的字符集是gbk而不是utf-8可能是网页过于简单的原因。

    五、带参数的get方法实现

    在上一个json中写也可以,新建一个json文件也可以,新建json文件后需要执行命令
    java -jar ./moco-runner-0.11.0-standalone.jar -p 8888 -c startupget.json
    重启服务
    示例如下:

    [
      {
        "description":"这是一个带参数的get请求",
        "request":{
          "uri":"/getdemo",
          "method":"get",
          "queries":{
            "name":"qinzhenxia",
            "age":"28"
          }
        },
        "response":{
          "text":"返回这是一个带参数的get请求",
          "headers":{
            "Content-Type":"text/html;charset=gbk"
          }
        }
      }
    ]
    

    在浏览器中访问:


    image.png

    六、模拟不带参数的post请求:
    "method":"post"

      {
        "description":"这是一个post请求",
        "request":{
          "uri":"/postdemo",
          "method":"post"
        },
        "response":{
          "text":"返回这是一个post请求",
          "headers":{
            "Content-Type":"text/html;charset=gbk"
          }
        }
      }
    

    在jemeter工具中执行post接口:


    image.png
    image.png

    七:模拟带form参数的post请求:
    post请求参数格式是key:value,不能使用queries,要使用forms

      {
        "description":"这是一个带参数的post请求,请求参数格式是key:value,不能使用queries,要使用forms",
        "request":{
          "uri":"/postwithparam",
          "method":"post",
          "forms":{
            "name":"qinzhenxia",
            "age":"28"
          }},
          "response":{
            "text":"这是一个带表单参数的post请求",
            "headers":{
              "Content-Type":"text/html;charset=gbk"
            }
          }
        }
    

    在jemeter中请求接口:

    image.png

    八、request请求中带cookies信息的get请求
    增加cookies值的设置:

      {
        "description":"这是一个request请求中带cookies信息的get请求",
        "request":{
          "uri":"/getwithcookies",
          "method":"get",
          "cookies":{
            "login":"true"
          }
        },
        "response":{
          "text":"返回这是一个request请求中带cookies信息的get请求",
          "headers":{
            "Content-Type":"text/html;charset=gbk"
          }
        }
      }
    

    在jemeter中请求接口时要先设置cookies信息:


    image.png

    cookies值设置:


    image.png

    执行结果:


    image.png image.png

    九、request请求中带cookies的post请求
    使用json格式的参数、返回结果也使用json格式

     {
       "description":"这是一个request请求中带cookies、使用json格式传参、返回结果为json格式的post请求",
       "request":{
         "uri":"/postwithcookiesandjson",
         "method":"post",
         "cookies":{
           "login":"true"
         },
         "json":{
           "name":"qinzhenxia",
           "age":"28"
         }
       },
       "response":{
         "status":200,
         "json":{
           "code":"0",
           "msg":"success",
           "p2pdata":{
             "name":"moguzhixing",
             "address":"beisanhuan"
           }
    
         }
       }
     }
    

    使用jemeter调接口,注意要先把cookie加入cookie管理器中:


    image.png

    请求接口的参数要写到bodydata中 是json格式的入参:


    image.png

    执行接口查看返回结果:


    image.png

    response请求中返回中文信息:

    {
        "description":"这是一个request请求中带cookies、使用json格式传参、返回结果为json格式的post请求,json返回中有中文,json可以解析中文",
        "request":{
          "uri":"/postwithcookiesandjsontwo",
          "method":"post",
          "cookies":{
            "login":"true"
          },
          "json":{
            "name":"moguzhixing",
            "age":"28"
          }
        },
        "response":{
          "status":200,
          "json":{
            "code":"0",
            "msg":"success",
            "p2pdata":{
              "name":"和平西桥",
              "address":"北三环中路"
            }
    
          }
        }
      }
    

    在jemeter中把cookies加入cookie管理器中,执行接口


    image.png

    十、模拟response返回中带有cookies信息的get请求

    {
        "description":"模拟response返回中带有cookies信息的get请求",
        "request":{
          "uri":"/getcookies"
        },
        "response":{
          "cookies":{
            "login":"true",
            "token":"1234567890"
    
          },
          "json":{
            "name":"zhoujielun",
            "age":"38"
          }
        }
      }
    

    请求返回结果:


    image.png

    十一、带有headers信息的mock请求
    十二、moco有重定向的接口
    需要用到"redirectTo":"/path",代码如下:

      {
        "description":"模拟重定向接口",
        "request":{
          "uri":"/redirectto"
        },
        "redirectTo":"/redirectedpath"
      },
      {
        "description":"模拟被重定向的接口",
        "request":{
          "uri":"/redirectedpath"
        },
        "response":{
          "text":"返回重定向结果",
          "headers":{
            "Content-Type":"text/html;charset=gbk"
          }
        }
      }
    

    在浏览器中输入http://localhost:8889/redirectto查看结果:

    image.png

    十三、使用httpclient调moco接口
    httpclient是模拟客户端发送http请求并获取返回结果的编程工具包,httpclient的使用方法:
    使用HttpClient发送请求、接收响应很简单,一般需要如下几步即可。

    1. 创建HttpClient对象。

    2. 创建请求方法的实例,并指定请求URL。如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。

    3. 如果需要发送请求参数,可调用HttpGet、HttpPost共同的setParams(HetpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。

    4. 调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。

    5. 调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。

    6. 释放连接。无论执行方法是否成功,都必须释放连接

    首先要加入依赖包,因为要用到testng,也加入testng的依赖包

            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
                <version>4.1.2</version>
            </dependency>
            <dependency>
                <groupId>org.testng</groupId>
                <artifactId>testng</artifactId>
                <version>6.9.10</version>
            </dependency>
    

    加入依赖包后,写入不带参数的get请求

    package com.course.httpclient.demo;
    
    import org.apache.http.HttpResponse;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.util.EntityUtils;
    import org.testng.annotations.Test;
    
    import java.io.IOException;
    
    public class MyHttpClient {
    
        //加入@Test注解
        @Test
        public void testHttpClient() throws IOException {
    
            //定义httpclient对象
            HttpClient httpClient1=new DefaultHttpClient();
            //HttpGet类,参数为要执行的url,实际测试中可以为接口地址
            HttpGet httpGet=new HttpGet("http://localhost:8889/redirectto");
    
            //用httpclient对象执行httpGet,并把返回结果存到httpresponse中
            HttpResponse httpResponse=httpClient1.execute(httpGet);
            //httpResponse的结果要调getEntity方法接收,同时需要转换成String类型才可以打印出来。
            String result= EntityUtils.toString(httpResponse.getEntity());
            System.out.println(result);
            ((DefaultHttpClient) httpClient1).close();
      
    
    
        }
    }
    
    

    运行后查看结果:


    image.png

    十四、模拟从上一个接口中获取cookie,供下一个接口入参使用
    moco的返回cookie的get接口代码如下:

      {
        "description":"模拟返回接口中有一个cookies,该cookie被用到下一个接口中的情况",
        "request":{
          "uri":"/response/cookies",
          "method":"get"
        },
        "response":{
          "cookies":{
            "token":"1234567890"
          },
          "json":{
            "name":"kunling",
            "age":25
          }
        }
      }
    

    moco的携带cookie的post接口如下:
    cookies的内容必须跟上一个接口的cookies内容一致才行。

    {
    "description":"这是一个request请求中带cookies、使用json格式传参、返回结果为json格式的post请求",
    "request":{
      "uri":"/post/with/cookies/usejson",
      "method":"post",
      "cookies":{
        "token":"1234567890"
      },
      "headers":{
        "Content-Type":"application/json;charset=gbk"
      },
      "json":{
        "name":"qinzhenxia",
        "age":"28"
      }
    },
    "response":{
      "status":200,
      "json":{
        "code":"0",
        "msg":"success",
        "p2pdata":{
          "name":"moguzhixing",
          "address":"北三环"
        }
      }
    }
    }
    

    httpclient调接口代码如下:

    package com.course.httpclient.cookies;
    
    import com.sun.xml.internal.ws.api.streaming.XMLStreamReaderFactory;
    import org.apache.http.HttpResponse;
    import org.apache.http.client.CookieStore;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.cookie.Cookie;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.util.EntityUtils;
    import org.json.JSONObject;
    import org.testng.Assert;
    import org.testng.annotations.BeforeTest;
    import org.testng.annotations.Test;
    
    import java.io.IOException;
    import java.util.List;
    import java.util.Locale;
    import java.util.ResourceBundle;
    
    public class MyCookiesForPost {
        //定义url存储请求地址
        private String url;
        //定义resourcebundle 从配置文件中获取配置新
        private ResourceBundle resourceBundle;
        //设置cookiestore全局变量
        private CookieStore cookieStore;
    
        @BeforeTest
        public void BeforeTest(){
            //调用getBundle方法,告诉resourceBundle从哪个配置文件中获取配置信息,定义Locale.CHINA是中文信息
            resourceBundle=ResourceBundle.getBundle("application", Locale.CHINA);
            //传入test.url配置名称,获取配置信息并赋值给url
            url=resourceBundle.getString("test.url");
        }
    
        /*
    模拟httpclient请求,并返回结果
     */
        @Test(enabled = false)
        public void testGetCookies() throws IOException {
            //拼接url
            String uri=url+resourceBundle.getString("test.responsecookies");
    
            //httpclient请求接口获取返回结果并打印
            HttpClient httpClient=new DefaultHttpClient();
            HttpGet httpGet=new HttpGet(uri);
            HttpResponse response=httpClient.execute(httpGet);
            String result= EntityUtils.toString(response.getEntity());
            System.out.println(result);
            ((DefaultHttpClient) httpClient).close();
    
    
        }
            /*
        模拟获取接口中返回的cookie,本接口返回的cookie供下一个接口使用。
         */
    
        @Test
        public void testGetAndResponseCookie() throws IOException {
            //拼接url
            String uri=url+resourceBundle.getString("test.responsecookies");
    
    
            //使用DefaultHttpClient类生成对象,不再使用HttpClient,这样才能获取到cookie
            DefaultHttpClient defaultHttpClient=new DefaultHttpClient();
    
            //使用getCookieStore()方法获取cookies信息,并赋值给cookieStore 全局变量
            cookieStore=defaultHttpClient.getCookieStore();
    
            //httpget请求
            HttpGet httpGet=new HttpGet(uri);
            HttpResponse httpResponse=defaultHttpClient.execute(httpGet);
            String result=EntityUtils.toString(httpResponse.getEntity());
            System.out.println(result);
    
            //获取cookies信息并打印出来
            List<Cookie> cookieStoreList=cookieStore.getCookies();
    
            //使用foreach循环返回cookie的name和value信息
            for(Cookie cookie : cookieStoreList){
                String name=cookie.getName();
                String value=cookie.getValue();
                System.out.println("cookiename:"+name+",cookievalue:"+value);
            }
            defaultHttpClient.close();
    
    
        }
    
        /*
        从上一个接口中获取cookie信息作为本接口的cookie
         */
        //使用dependsOnMethods = {"testGetAndResponseCookie"}参数,依赖testGetAndResponseCookie方法,也就是上一个方法返回的cookie信息
        @Test(dependsOnMethods = {"testGetAndResponseCookie"})
        public void testpostmethod() throws IOException {
            String uri=url+resourceBundle.getString("test.postwithcookiesusejson");
    
            //生成httpclient对象
            DefaultHttpClient defaultHttpClient=new DefaultHttpClient();
    
            //创建post请求
            HttpPost httpPost=new HttpPost(uri);
    
            //使用json入参,入参是中文时不行。
            JSONObject param=new JSONObject();
            param.put("name","qinzhenxia");
            param.put("age","28");
    
            //设置请求头header
            httpPost.setHeader("Content-Type","application/json;charset=gbk");
            //传入参数
            StringEntity entity=new StringEntity(param.toString(),"gbk");
            httpPost.setEntity(entity);
    
            //设置cookie是用defaultHttpClient调setCookieStore方法,不是用httppost调
            defaultHttpClient.setCookieStore(this.cookieStore);
    
            //执行请求并接收返回结果
            HttpResponse httpResponse = defaultHttpClient.execute(httpPost);
            String result=EntityUtils.toString(httpResponse.getEntity());
            System.out.println(result);
    
    
            //判断返回code值
            int statuscode=httpResponse.getStatusLine().getStatusCode();
            Assert.assertEquals(statuscode,200);
    
            //获取返回结果并转换为jsonobject格式,然后获取某个具体的值通过断言判断
            JSONObject resultjson=new JSONObject(result);
            String msg =resultjson.getString("msg");
            //判断msg等于success
            Assert.assertEquals(msg,"success");
    
    
            JSONObject p2pdata=resultjson.getJSONObject("p2pdata");
    
            String address=p2pdata.getString("address");
            System.out.println(address);
            Assert.assertEquals(address,"北三环");
    
        }
    
    }
    
    

    相关文章

      网友评论

          本文标题:Moco接口框架应用实战

          本文链接:https://www.haomeiwen.com/subject/yuolfqtx.html