網頁

2022/6/30

Golang Web API測試

Go Web API測試。


範例環境:

  • Go 1.18


受測程式

POST|/employee為受測的API,請求交由EmployeeHandler處理,最終返回request body的JSON字串。

main.go

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
)

func main() {
    http.HandleFunc("/employee", EmployeeHandler)
    http.ListenAndServe(":8080", nil)
}

func EmployeeHandler(w http.ResponseWriter, r *http.Request) {
    switch r.Method {
    case http.MethodPost:
        b, err := ioutil.ReadAll(r.Body)
        if err != nil {
            panic(err)
        }
        w.Header().Set("Content-Type", "application/json")
        w.WriteHeader(http.StatusCreated)
        fmt.Fprint(w, string(b))
    default:
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
    }
}


測試程式

下面main_test.go測試main.goTestEmployeeHandler_Post直接測試EmployeeHandlerTestEmployeeEndpoint_Post則測試POST|/employee API。不過注意這裡沒考慮到如果有service的mock需求。

main_test.go

package main

import (
    "io"
    "net/http"
    "net/http/httptest"
    "strings"
    "testing"
)

func TestEmployeeHandler_Post(t *testing.T) {
    // create testing request and response writer
    w := httptest.NewRecorder()
    body := "{\"id\":1,\"name\":\"John\",\"age\":33}"
    r := httptest.NewRequest(http.MethodPost, "/employee", strings.NewReader(body))

    // send testing request and response writer to target handler
    EmployeeHandler(w, r)
    if w.Result().StatusCode != http.StatusCreated {
        t.Errorf("unexpected status code=%d", w.Result().StatusCode)
    }

    // read response body
    b, err := io.ReadAll(w.Body)
    if err != nil {
        t.Errorf("read response body error, err=%v", err)
    }
    // verify result as expected
    result := string(b)
    if result != body {
        t.Errorf("expected %v, but %v", body, result)
    }
}

func TestEmployeeEndpoint_Post(t *testing.T) {
    // create mock server with target endpoint handler
    server := httptest.NewServer(http.HandlerFunc(EmployeeHandler))
    defer server.Close()

    // create http request with mock server's url
    body := "{\"id\":1,\"name\":\"John\",\"age\":33}"
    req, err := http.NewRequest(http.MethodPost, server.URL, strings.NewReader(body))
    if err != nil {
        t.Errorf("create request error, err=%v", err)
    }

    // send http request to mock server
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        t.Errorf("send request error, err=%v", err)
    }

    if resp.StatusCode != http.StatusCreated {
        t.Errorf("unexpected status code=%d", resp.StatusCode)
    }

    // read response body
    b, err := io.ReadAll(resp.Body)
    if err != nil {
        t.Errorf("read response body error, err=%v", err)
    }
    defer resp.Body.Close()

    // verify result as expected
    result := string(b)
    if result != body {
        t.Errorf("expected %v, but %v", body, result)
    }
}


執行測試

在專案跟目錄以命令列輸入go test -v結果如下。

$ go test -v
=== RUN   TestEmployeeHandler_Post
--- PASS: TestEmployeeHandler_Post (0.00s)
=== RUN   TestEmployeeEndpoint_Post
--- PASS: TestEmployeeEndpoint_Post (0.00s)
PASS
ok      abc.com/demo    0.381s

github


沒有留言:

張貼留言