精华内容
下载资源
问答
  • Golang单元测试之httptest使用

    千次阅读 2019-05-05 15:28:01
    ————————————————————————...现在有一个需求那就是,我们需要使用Golang的net/http包中的http.Get(url)方法去向服务器端请求数据,但是负责服务端的同事并没有将接口实现(可能是同事太忙...

    转载:https://blog.csdn.net/lavorange/article/details/73369153 

    —————————————————————————————————————————————————

    现在有一个需求那就是,我们需要使用Golang的net/http包中的http.Get(url)方法去向服务器端请求数据,但是负责服务端的同事并没有将接口实现(可能是同事太忙,把妹,喝酒,扯淡, XO等等)以至于你只知道返回数据的json格式,然而无法请求到真实的数据,但是你的工作进度并不能因为同事而耽误,需要测试你的代码的正确性,那么怎么办?办法就是通过单元测试中的httptest,实现http server,并设置好返回值,那么http.Get(url)的请求就会直接打到单元测试的http server上,同时得到你设置好的返回值,你就可以继续去处理数据,测试你的代码逻辑了。

    一、导入

    设置一个场景:

    需要向服务器端去获取住址为"shanghai"的所有人的信息,请求函数为:

    func GetInfo(api string) ([]Person, error) 


    这个方法包括:


    1.向服务端发送get请求获取数据

    2.将数据序列化person的信息

    3.如果出现错误,返回error

    需要测试的内容:

    1.需要测试返回值是我们设置的值:

    var personResponse = []Person{
                  {
                    Name : "wahaha",
                    Address : "shanghai",
                    Age : 20,
                  },
                          {
                    Name : "lebaishi",
                    Address : "shanghai",
                    Age : 10,
                  },
                 }

    2.需要测试GetInfo方法是发送了正确的http请求,及method是否正确,路径是否正确,请求参数是否正确。
    3.返回状态码是否正确。

    二、Golang testing基础

    Go提供了一个testing包来写单元测试。假设我们有个文件叫person.go,那么我们的测试文件就需要明明为person_test.go

    package person
     
    import (
        "testing"
    )
     
    func TestPublishUnreachable(t *testing.T) {
        api := "http://localhost:8090"
        _, err := GetInfo(api)
        if err != nil {
            t.Errorf("GetInfo() return an error")
        }
    }


    注:
    >测试函数以Test*开头。

    >测试函数将*testing.T作为参数,可以在失败的情况下使用Errorf()方法。

    >在包内使用go test -v来运行单元测试。

    这个单元测试将会失败,因为我们还没有实现GetInfo()方法,下面是person.go文件:

    package person
     
    import (
        "net/http"
        "fmt"
    )
     
    const (
        ADDRESS = "shanghai"
    )
     
    type Person struct {
        Name string `json:"name"`
        Address string `json:"address"`
        Age int `json:"age"`
    }
     
    func GetInfo(api string) ([]Person, error) {
        url := fmt.Sprintf("%s/person?addr=%s", api, ADDRESS)
        resp, err := http.Get(url)
     
        if err != nil {
            return []Person{}, err
        }
     
        if resp.StatusCode != http.StatusOK {
            return []Person{}, fmt.Errorf("get info didn’t respond 200 OK: %s", resp.Status)
        }
     
        return nil, nil
    }


    当然运行go test也会返回一个错误,因为请求地址的问题,请求的并不是一个实际上的http server,那么自然也不会有正常的返回。

    三、Golang httptest

    上面一个例子很有用,但是如何去发送一个真正的http request而不去真正的启动一个http server(亦或者请求任意的server)?答案是使用Go 的httptest包,这个包可以非常简单的创建一个测试的http server,那么下面我们将展示一下完整的代码,并解释一下整体的测试流程:

    person.go:

    package person
     
    import (
        "net/http"
        "fmt"
        "io/ioutil"
        "encoding/json"
     
        "github.com/astaxie/beego/logs"
    )
     
    const (
        ADDRESS = "shanghai"
    )
     
    type Person struct {
        Name string `json:"name"`
        Address string `json:"address"`
        Age int `json:"age"`
    }
     
    func GetInfo(api string) ([]Person, error) {
        url := fmt.Sprintf("%s/person?addr=%s", api, ADDRESS)
        resp, err := http.Get(url)
     
        defer resp.Body.Close()
     
        if err != nil {
            return []Person{}, err
        }
     
        if resp.StatusCode != http.StatusOK {
            return []Person{}, fmt.Errorf("get info didn’t respond 200 OK: %s", resp.Status)
        }
     
        bodyBytes, _ := ioutil.ReadAll(resp.Body)
        personList := make([]Person,0)
        err = json.Unmarshal(bodyBytes, &personList)
        if err != nil {
            logs.Error("decode data fail")
            return []Person{}, fmt.Errorf("decode data fail")
        }
     
        return personList, nil
    }


    person_test.go

    package person
     
    import (
        "testing"
        "net/http/httptest"
        "net/http"
        "fmt"
        "encoding/json"
    )
     
    var personResponse = []Person{
                  {
                    Name : "wahaha",
                    Address : "shanghai",
                    Age : 20,
                  },
                          {
                    Name : "lebaishi",
                    Address : "shanghai",
                    Age : 10,
                  },
                 }
     
    var personResponseBytes, _ = json.Marshal(personResponse)
     
    func TestPublishWrongResponseStatus(t *testing.T) {
        ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            w.WriteHeader(http.StatusOK)
            w.Write(personResponseBytes)
            if r.Method != "GET"{
                t.Errorf("Expected 'GET' request, got '%s'", r.Method)
            }
            if r.URL.EscapedPath() != "/person" {
                t.Errorf("Expected request to '/person', got '%s'", r.URL.EscapedPath())
            }
            r.ParseForm()
            topic := r.Form.Get("addr")
            if topic != "shanghai" {
                t.Errorf("Expected request to have 'addr=shanghai', got: '%s'", topic)
            }
        }))
     
        defer ts.Close()
        api := ts.URL
        fmt.Println("url:", api)
        resp, _ := GetInfo(api)
     
        fmt.Println("reps:", resp)
    }


    解释一下:
    >我们通过httptest.NewServer创建了一个测试的http server

    >读请求设置通过变量r *http.Request,写变量(也就是返回值)通过w http.ResponseWriter

    >通过ts.URL来获取请求的URL(一般都是<http://ip:port>)

    >通过r.Method来获取请求的方法,来测试判断我们的请求方法是否正确

    >获取请求路径:r.URL.EscapedPath(),本例中的请求路径就是"/person"

    >获取请求参数:r.ParseForm,r.Form.Get("addr")

    >设置返回的状态码:w.WriteHeader(http.StatusOK)

    >设置返回的内容(这就是我们想要的结果):w.Write(personResponseBytes),注意w.Write()接收的参数是[]byte,因此需要将object对象列表通过json.Marshal(personResponse)转换成字节。

    综上,我们可以通过不发送httptest来模拟出httpserver和返回值来进行自己代码的测试了。

    展开全文
  • HttpTest4Net.rar

    热门讨论 2014-11-06 10:16:18
    压力测试软件,能够模拟用户访问,测试http服务器的抗压能力
  • golang web开发 Handler测试利器httptest

    千次阅读 2017-10-16 11:43:23
    test是golang语言的一部分,golang提供了非常强大的...我们用go开发一个Web Server后,打算单元测试写的handler函数,在不知道httptest之前,使用比较笨的方法 就是编译运行该Web Server后,再用go编写一个客户端程...

    test是golang语言的一部分,golang提供了非常强大的测试方法。单元测试,压力测试可以参见 golang 1.7之后高级测试方法之子测试,子基准测试(subtest sub-benchmarks)

    我们用go开发一个Web Server后,打算单元测试写的handler函数,在不知道httptest之前,使用比较笨的方法
    就是编译运行该Web Server后,再用go编写一个客户端程序向该Web Server对应的route发送数据然后解析
    返回的数据。这个方法测试时非常麻烦,使用httptest来测试的话就非常简单,可以和testing测试一起使用。

    httptest基本使用方法

    假设在server中handler已经写好

    http.HandleFunc("/health-check", HealthCheckHandler)
    
    func HealthCheckHandler(w http.ResponseWriter, r *http.Request) {
        // A very simple health check.
        w.WriteHeader(http.StatusOK)
        w.Header().Set("Content-Type", "application/json")
    
        // In the future we could report back on the status of our DB, or our cache 
        // (e.g. Redis) by performing a simple PING, and include them in the response.
        io.WriteString(w, `{"alive": true}`)
    }

    测试如下:

    import (
        "net/http"
        "net/http/httptest"
        "testing"
    )
    
    func TestHealthCheckHandler(t *testing.T) {
        //创建一个请求
        req, err := http.NewRequest("GET", "/health-check", nil)
        if err != nil {
            t.Fatal(err)
        }
    
        // 我们创建一个 ResponseRecorder (which satisfies http.ResponseWriter)来记录响应
        rr := httptest.NewRecorder()
    
        //直接使用HealthCheckHandler,传入参数rr,req
        HealthCheckHandler(rr, req)
    
        // 检测返回的状态码
        if status := rr.Code; status != http.StatusOK {
            t.Errorf("handler returned wrong status code: got %v want %v",
                status, http.StatusOK)
        }
    
        // 检测返回的数据
        expected := `{"alive": true}`
        if rr.Body.String() != expected {
            t.Errorf("handler returned unexpected body: got %v want %v",
                rr.Body.String(), expected)
        }
    }

    然后就可以使用run test来执行测试.

    如果Web Server有操作数据库的行为,需要在init函数中进行数据库的连接。

    参考官方文档中的样例编写的另外一个测试代码:

    func TestHealthCheckHandler2(t *testing.T) {
        reqData := struct {
            Info string `json:"info"`
        }{Info: "P123451"}
    
        reqBody, _ := json.Marshal(reqData)
        fmt.Println("input:", string(reqBody))
        req := httptest.NewRequest(
            http.MethodPost,
            "/health-check",
            bytes.NewReader(reqBody),
        )
    
        req.Header.Set("userid", "wdt")
        req.Header.Set("commpay", "brk")
    
        rr := httptest.NewRecorder()
        HealthCheckHandler(rr, req)
    
        result := rr.Result()
    
        body, _ := ioutil.ReadAll(result.Body)
        fmt.Println(string(body))
    
        if result.StatusCode != http.StatusOK {
            t.Errorf("expected status 200,",result.StatusCode)
        }
    }

    注意不同的地方
    - http.NewRequest替换为httptest.NewRequest。
    - httptest.NewRequest的第三个参数可以用来传递body数据,必须实现io.Reader接口。
    - httptest.NewRequest不会返回error,无需进行err!=nil检查。
    - 解析响应时没直接使用ResponseRecorder,而是调用了Result函数。

    结合context使用

    func TestGetProjectsHandler(t *testing.T) {
        req, err := http.NewRequest("GET", "/api/users", nil)
        if err != nil {
            t.Fatal(err)
        }
    
        rr := httptest.NewRecorder()
        // e.g. func GetUsersHandler(ctx context.Context, w http.ResponseWriter, r *http.Request)
        handler := http.HandlerFunc(GetUsersHandler)
    
        // Populate the request's context with our test data.
        ctx := req.Context()
        ctx = context.WithValue(ctx, "app.auth.token", "abc123")
        ctx = context.WithValue(ctx, "app.user",
            &YourUser{ID: "qejqjq", Email: "user@example.com"})
    
        // Add our context to the request: note that WithContext returns a copy of
        // the request, which we must assign.
        req = req.WithContext(ctx)
        handler.ServeHTTP(rr, req)
    
        // Check the status code is what we expect.
        if status := rr.Code; status != http.StatusOK {
            t.Errorf("handler returned wrong status code: got %v want %v",
                status, http.StatusOK)
        }
    }

    参考

    httptest doc
    Testing Your (HTTP) Handlers in Go

    推荐干货满满的技术专栏
    这里写图片描述

    这里写图片描述[toc]

    展开全文
  • 基于gin的单元测试之httptest

    千次阅读 2018-04-04 16:53:04
    正好借着这次单元测试和持续集成,我们引入了httptest框架,结合gin来做接口单元测试。 httptest是golang官方提供的一个包,位于/src/net/http/httptest下。 其原理的话我也看了源码研究了下,这里大致说下,它有...

    目前我们的后端服务提供大量的restful api接口,每次上线都需要测试那边回归一遍这些接口,造成人力的浪费。正好借着这次单元测试和持续集成,我们引入了httptest框架,结合gin来做接口单元测试。

    httptest是golang官方提供的一个包,位于/src/net/http/httptest下。

    其原理的话我也看了源码研究了下,这里大致说下,它有一个ResponseRecorder结构体,它实现了http.ResponseWriter,同时它自身又包含了http.Response,前者是server端维度下的response,后者是client端维度下的response,也就是说,ResponseRecorder同时实现了server和client的功能。

    好接下来看看如何使用httptest

    httptest构建

     // Get 根据特定请求uri,发起get请求返回响应
    func Get(uri string, router *gin.Engine) []byte {
        // 构造get请求
        req := httptest.NewRequest("GET", uri, nil)
        // 初始化响应
        w := httptest.NewRecorder()
    
        // 调用相应的handler接口
        router.ServeHTTP(w, req)
    
        // 提取响应
        result := w.Result()
        defer result.Body.Close()
    
        // 读取响应body
        body,_ := ioutil.ReadAll(result.Body)
        return body
    }
    
    // PostForm 根据特定请求uri和参数param,以表单形式传递参数,发起post请求返回响应
    func PostForm(uri string, param url.Values, router *gin.Engine) []byte {
    
        // 构造post请求
        req := httptest.NewRequest("POST", uri, strings.NewReader(param.Encode()))
        req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
    
        // 初始化响应
        w := httptest.NewRecorder()
    
        // 调用相应handler接口
        router.ServeHTTP(w, req)
    
        // 提取响应
        result := w.Result()
        defer result.Body.Close()
    
        // 读取响应body
        body, _ := ioutil.ReadAll(result.Body)
        return body
    }

    在gin中注册路由,并写了两个接口样例

    
    regAdmin := router.Group("/quote")
    regAdmin.GET("/ge", Ge)
    regAdmin.POST("/pos", Pos)
    
    
    type TestForPost struct {
        Strname string  `form:"strname" binding:"required"`
        Number int  `form:"number" binding:"required"`
    }
    
    
     // Get接口
    func Ge(c *gin.Context)  {
        c.String(http.StatusOK, "success")
    }
    
    
     // Post接口
    func Pos(c *gin.Context) {
        req := &TestForPost{}
        if err := c.ShouldBindWith(req, binding.Form); err != nil {
            fmt.Println("bind error",err)
            c.JSON(http.StatusOK, gin.H{
                "errno":"1",
                "errmsg":"参数不匹配",
                "data":"",
            })
            return
        }
        c.JSON(http.StatusOK, gin.H{
            "errno":"0",
            "errmsg":"Null",
            "data":req,
        })
    }

    写单元测试

    type Response struct {
        Errno string `json:"errno"`
        Errmsg string `json:"errmsg"`
        Data TestForPost `json:"data"`
    }
    
    func TestOnGetStringRequest(t *testing.T) {
    
        // 初始化请求地址
        url:="/quote/ge"
        // 发起Get请求
        body := Get(url, router)
    
        // 判断响应是否与预期一致
        if string(body) != "success" {
            t.Errorf("响应字符串不符,body:%v\n",string(body))
        }
    
        convey.Convey("测试GET接口", t, func() {
            convey.So(string(body), convey.ShouldEqual, "success")
        })
    }
    
    
    func TestOnPostRequestForForm(t *testing.T) {
        // 初始化请求地址和请求参数
        uri := "/quote/pos"
    
        param := url.Values{
            "strname":{"test"},
            "number":{"1"},
        }
        // 发起post请求,以表单形式传递参数
        body := PostForm2(uri, param, router)
        //body := PostForm3(uri, param, router)
    
        // 解析响应,判断响应是否与预期一致
        response := &Response{}
        if err := json.Unmarshal(body, response); err != nil {
            t.Errorf("解析响应出错,err:%v\n",err)
        }
        t.Log(response.Data)
        if response.Data.Strname != "test" {
            t.Errorf("响应数据不符,errmsg:%v, data:%v\n",response.Errmsg,response.Data.Strname)
        }
        convey.Convey("测试POST接口", t, func() {
            convey.So(response.Data.Strname, convey.ShouldEqual, "test")
        })
    }

    完成

    展开全文
  • Spring junit test mock模拟http接口测试

    千次阅读 2018-11-29 15:15:12
    public void testMock() throws Exception { mockMvc.perform( MockMvcRequestBuilders.get("/mockTest") .param("name", "demo") ) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo...

    很多时候对项目中的api接口大多是启动项目后用浏览器调用一下接口进行测试,或者用swagger,还有postman等工具,其实在单测里面也可以模拟浏览器进行接口测试。

    先定义一个api接口,

    @RequestMapping(value = "/mockTest", method = RequestMethod.GET)
    @ResponseBody
        public String mock(
                @RequestParam(value = "name") String name
        ) {
            return "参数:" + name;
        }
    

    在单测类里面,添加mock对象

    	private MockMvc mockMvc;
    	
        @Autowired
        private WebApplicationContext context;
    
    
        @Before
        public void before() throws Exception {
            mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
        }
    
        @Test
        public void testMock() throws Exception {
            mockMvc.perform(
                    MockMvcRequestBuilders.get("/mockTest")
                            .param("name", "demo")
            )
                    .andExpect(MockMvcResultMatchers.status().isOk())
                    .andDo(MockMvcResultHandlers.print())
            ;
        }
    
    展开全文
  • Idea Test Restful Web Service

    千次阅读 2019-12-25 19:18:38
    后台调试自测接口,你是否还在用Postman呢? 今天给大家推荐一款Idea自带的工具...Tools—HTTP Client —Test RESTful Web Services 2.使用Test Restful Web Service 执行第一步操作即可打开如下弹框(接口和数据请...
  • 这个教程尝试去详细一步一步解析HTTP/HTTPS测试,对于从未使用过JMeter初学者,这是一个简单途径用JMeter去构建http测试。 JMeter 配置 从JMeter2.10,recording(录制)对于处理内嵌资源和创建证书已经有很大提升。 ...
  • 文章目录首先导入Springboot-test包编写测试用例JSONPATH 首先导入Springboot-test包 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tes.....
  • 写了一个程序,gcc test.c -o test 的时候 出现奇怪的提示,不是warning 也不是error, # gcc -g test.c -o test /usr/bin/ld: cannot open output file test: Is a directory collect2: ld returned 1 exit status...
  • springboot test

    万次阅读 2019-03-21 15:16:57
    在src/main下建立UserService类,对其进行单于测试,生产其单元测试类(使用command+shift+T快捷键),生成的test类在src/test下 @Service public class UserService { public Integer ...
  • golang test测试使用

    千次阅读 2018-06-02 21:42:52
    一步步教你编写可测试的Go语言代码相信每位编程开发者们应该都知道,Golang作为一门标榜工程化的语言,提供了非常简便、实用的编写单元测试的能力。... 例如: 1、文件名必须以xx_test.go命名 ...
  • 打开idea并选择创建新项目,进入如下页面,选择Spring Initializr,选择右侧jdk以及选择Custom,将地址修改为http://start.srping.io,选择Next,填写Group和artifct,选择Next2. 进入如下页面,选择Spring boot的依赖...
  • unity Test Tools 测试

    千次阅读 2015-09-13 14:54:24
    孙广东 2015.9.13.../content/13802https://bitbucket.org/Unity-Technologies/unitytesttoolshttps://bitbucket.org/Unity-Technologies/unitytesttools/wiki/Homehttp://unity
  • SpringBoot test

    万次阅读 多人点赞 2018-12-04 09:59:21
    前言 mac上idea快捷键,command+shift+T根据类生成快捷键。...在src/main下建立UserService类,对其进行单于测试,生产其单元测试类(使用command+shift+T快捷键),生成的test类在src/test下 @Servi...
  • {192.168.3.86:web.test.rspcode[3.86_http_status,3.86_http_status].last(0)}<>200 and {192.168.3.86:web.test.rspcode[3.86_http_status,3.86_http_status].last(1)}<>200 and {192.168.3.86:web.test.rspcode...
  • INSTALL_FAILED_TEST_ONLY的原因

    万次阅读 多人点赞 2018-05-15 11:33:08
    有一天给测试同学打了个deubg 包发现无法安装,提示无法解析,使用adb install 安装后提示INSTALL_FAILED_TEST_ONLY,原来是Android Studio 3.0会在debug apk的manifest文件application标签里自动添加 android:...
  • 目录以及作用 api:为了更好地对接口描述进行管理,推荐使用独立的文件对接口描述进行存储,即每个文件对应一个接口描述。接口定义描述的主要内容包括:name、... testsuites:测试用例集,当测试用例数量...
  • spring-test.jar

    千次下载 热门讨论 2010-08-27 15:12:24
    spring-test.jar 单独下这个的很少,因为他就在spring-framework-2.5.5.zip里,只要你下有spring2.5。 spring 官方下载地址: http://www.springsource.com/download/
  • AB test详解

    万次阅读 2020-12-04 13:05:03
    AB test用于推荐系统在线测试 AB test一个总的目的和意图是,判断哪种UI或rerank策略更优,通过事实的依据判断哪种测苦厄更符合用户的习惯和需求。 一、背景介绍 无法衡量就无法优化,对于互联网产品而言,不仅是...
  • Linux下使用Speedtest测试网速

    万次阅读 2016-11-08 11:54:05
    Speedtest是用来测试网络性能的开源软件,在Linux下面安装Speedtest可以用来测试网络出口的上传和下载速度,帮助排查网络方面导致的故障。 Speedtest介绍 由于公司几个项目用户访问的时候响应较慢,项目...
  • Quartus II使用Testbench

    千次阅读 2019-11-15 16:06:45
    最近做实验要用Testbench,本来想照着网上教程做一做,结果太坑了,所以决定自己写一篇。我用的是Quartus II 16.0,如果版本不同没有关系,相差不会很大。 在开始之前,首先要确定两件事情: 1.你的电脑安装了...
  • JMeter组件之Test Fragment

    千次阅读 2018-05-12 16:01:00
    1. 概念JMeter中的Test Fragment,是控制器上一个种特殊的线程组,它在测试树上与线程组处于一个层级。但使用时需要和include Controller或者Module Controller配合。它的主要作用是模块化测试过程,类似于编程语言...
  • 网络测速神器:SpeedTest深度指南

    千次阅读 2020-09-03 08:17:25
    貌似目的服务器不存在,超时了 -mini MINI URL of the Speedtest Mini server //指定源ip,其实就是本机ip,可以用ifconifg查看本机ip --source SOURCE Source IP address to bind to //设置http超时时间,默认为10s...
  • js中正则表达式test()方法

    万次阅读 2018-10-08 12:45:51
    regexObj.test(str)方法:测试正则表达式与指定字符串是否匹配 PS:test()方法只需要待测试字符串中包含了要测试的字符串就是ture 1.匹配一段字符串 /123456/.test("123456") //ture ...
  • Test your vocabulary

    千次阅读 2019-11-18 13:24:34
    www.testyourvocab.com ... http://my.vocabularysize.com/ According to the last website: How large a vocabulary is needed for reading and listening? Skill Size ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,097,132
精华内容 838,852
关键字:

httptest