Golang單元測試之httptest使用
現在有一個需求那就是,我們需要使用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.需要測試返回值是我們設定的值:
2.需要測試GetInfo方法是傳送了正確的http請求,及method是否正確,路徑是否正確,請求引數是否正確。var personResponse = []Person{ { Name : "wahaha", Address : "shanghai", Age : 20, }, { Name : "lebaishi", Address : "shanghai", Age : 10, }, }
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來執行單元測試。
這個單元測試將會失敗,因為我們還沒有實現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和返回值來進行自己程式碼的測試了。
Author:憶之獨秀
Email:[email protected]
相關推薦
Golang單元測試之httptest使用
現在有一個需求那就是,我們需要使用Golang的net/http包中的http.Get(url)方法去向伺服器端請求資料,但是負責服務端的同事並沒有將介面實現(可能是同事太忙,把妹,喝酒,扯淡, XO
基於gin的單元測試之httptest
目前我們的後端服務提供大量的restful api介面,每次上線都需要測試那邊迴歸一遍這些介面,造成人力的浪費。正好藉著這次單元測試和持續整合,我們引入了httptest框架,結合gin來做介面單元測試。 httptest是golang官方提供的一個包,位於/
golang單元測試之mock
搞單元測試,如果碰到這些情況: 1,一個函式,內部包含了很多並且很深的呼叫,但是如果單單測這個函式,其實實現的功能很簡單。 2,一個函式,包含了其他還未實現的呼叫。 3,函式內部對資料的要求極為苛刻。 那麼這時候就可以考慮使用mock來處理。 mock
單元測試之Stub和Mock
下載 我們 並且 試用 sample 註入 mes oge new 單元測試之Stub和Mock FROM:http://www.cnblogs.com/TankXiao/archive/2012/03/06/2366073.html 在做單元測試的時候,我們會發現我
python + unittest 做單元測試之學習筆記
stl unittest 例子 gin pre log script 有關 assert 單元測試在保證開發效率、可維護性和軟件質量等方面有很重要的地位,所謂的單元測試,就是對一個類,一個模塊或者一個函數進行正確性檢測的一種測試方式。 這裏主要是就應用 python + u
論單元測試之重要性
表單 曾經 mybatis 服務 request 第一個 完成 分離 能說 單元測試的重要性不言而喻,自我開發生涯以來,從很少註釋過過場場,到非常重視。 單元測試為什麽會讓人忽視呢? 通常情況像一些查詢或者增刪改之類,拿我來說,即便報錯我大概一掃,我就知道錯誤是什麽了,該如
python筆記24-unittest單元測試之mock.patch
rom Coding int self. 錯誤 測試用例 方法 org auto 前言 上一篇python筆記23-unittest單元測試之mock對mock已經有初步的認識, 本篇繼續介紹mock裏面另一種實現方式,patch裝飾器的使用,patch() 作為函數裝飾器
補習系列-springboot 單元測試之道
try 精彩 一次 run rest spec ner hat ltm 目錄 目標 一、About 單元測試 二、About Junit 三、SpringBoot-單元測試 項目依賴 測試樣例 四、Mock測試 五、最後 目標 了解 單元測試的背景 了解如何 利用
單元測試之Mock(Moq)
inter 商品 void 簡單 calc 不用 準備 targe ted Mock翻譯為“嘲弄”,其實就是偽造一個對象用於測試。在單元測試中,被測試方法依賴於其他對象時,為了測試簡單一般“偽造”一個這個對象;這樣做的目的: 不用考慮依賴對象的復雜性(方便準備測試數據)
java單元測試之如何實現非同步介面的測試案例
測試是軟體釋出的重要環節,單元測試在實際開發中是一種常用的測試方法,java單元測試主要用junit,最新是junit5,本人開發一般用junit4。因為單元測試能夠在軟體模組組合之前儘快發現問題,所以實際開發中投入產出比很高。實際使用難免會遇到非同步操作的介面測試,最常用的情景是別人家的SD
前端單元測試之Jest
概述 關於前端單元測試的好處自不必說,基礎的介紹和知識可以參考之前的部落格連結:React Native單元測試。在軟體的測試領域,測試主要分為:單元測試、整合測試和功能測試。 單元測試:在計算機程式設計中,單元測試(英語:Unit Testing)又稱為模組測試, 是針對程式模組(軟體設計的最小單
spring boot單元測試之druid NullPointException
最近在使用spring boot 對 Controller 進行單元測試時,發現 druid 竟然丟擲了空指標異常。原因是,使用了druid的監控,需要經過druid的 Filter 攔截器,但是spr
powermockito單元測試之深入實踐
概述 由於最近工作需要, 在專案中要做單元測試, 以達到指定的測試用例覆蓋率指標。專案中我們引入的powermockito來編寫測試用例, JaCoCo來監控單元測試覆蓋率。關於框架的選擇, 網上討論mockito和powermockito孰優孰劣的文章眾多, 這裡就不多做闡述, 讀者如有興趣可自行了解。
phpunit 單元測試之程式碼覆蓋率
最近團隊在不斷完善專案中的單元測試用例,會用到程式碼覆蓋率分析,本來以為 homestead 應該預設安裝了 xdebug ,所以使用 phpunit --coverage-html ./tests/codeCoverage 來生成 html 報告,但是執行後提示如下錯誤 Error: No
談談單元測試之(四):測試工具 TestNG
前言 上一篇文章《測試工具 JUnit 4》中提到了 JUnit 4,並對 JUnit 4 做了簡單的討論,這篇文章我們將要圍繞另一款測試工具討論 —— TestNG。其實,這篇文章應該寫在《測試工具 JUnit 3》之後,和《測試工具 JU
談談單元測試之(三):測試工具 JUnit 4
前言 上一篇文章《測試工具 JUnit 3》簡單的討論了 JUnit 3 的使用以及內部的方法。這篇文章將會在 JUnit 3 的基礎上,討論一下 JUnit 4 的新特性。同時,與 JUnit 3 做一個簡單的對比。那麼,廢話就不多說了,直
談談單元測試之(二):測試工具 JUnit 3
前言 上一篇文章《 為什麼要進行煩人的單元測試?》討論了一下現階段軟體開發中,程式設計師們測試情況的現狀。這篇文章中,我打算介紹一下單元測試的工具(外掛),並且推薦大家以後在開發中,真正的用上單元測試,用好單元測試。
談談單元測試之(一):為什麼要進行煩人的單元測試?
前言 最近,在網上看到過一個調查,調查的內容是“程式設計師在專案開發中編寫單元測試的情況”。當然,至於調查的結果,我想聰明的你已經可以猜到了。高達 58.3% 的比例,一般情況下不寫單元測試,只有偶爾的情況才會寫寫。16.6%
Java單元測試之JUnit篇
JUnit4通過註解的方式來識別測試方法。目前主要註解有: @BeforeClass 全域性只會執行一次,而且是第一個執行,且必須為static void @Before 在測試方法執行之前執行,即初
Golang單元測試、效能測試
Test 單元測試 testing包提供了對Go包的自動測試支援。 這是和go test 命令相呼應的功能, go test 命令會自動執行所以符合格式 func TestXXX(t *testing.T) 的函式。 Benchmark 效能測試 Functions of the f