首页 > 解决方案 > 在访问日志中间件的情况下如何进行单元测试

问题描述

我有一个中间件来记录此服务访问。但是我多次在谷歌上搜索时对进行单元测试感到困惑。我还没有找到解决这个问题的正确方法

package accesslog

import (
    "net/http"
    "time"

    "github.com/go-chi/chi/middleware"

    "transactionService/pkg/log"
)

func Handler(logger log.Logger) func(next http.Handler) http.Handler {
    return func(next http.Handler) http.Handler {
        fn := func(w http.ResponseWriter, r *http.Request) {
            ctx := r.Context()
            ctx = log.WithRequest(ctx, r)
            ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor)

            start := time.Now()
            defer func() {
                logger.With(ctx, "duration", time.Since(start), "status", ww.Status()).
                    Infof("%s %s %s %d %d", r.Method, r.URL.Path, r.Proto, ww.Status(), ww.BytesWritten())
            }()

            next.ServeHTTP(ww, r.WithContext(ctx))
        }

        return http.HandlerFunc(fn)
    }
}


标签: unit-testinggomiddlewarego-chi

解决方案


解决了,这是我解决它的代码

package accesslog

import (
    "io"
    "io/ioutil"
    "net/http"
    "net/http/httptest"
    "testing"

    "github.com/go-chi/chi"

    "transactionService/pkg/log"
)

func TestHandler(t *testing.T) {
    logger, _ := log.NewForTest()

    r := chi.NewRouter()
    r.Use(Handler(logger))
    r.Get("/", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        _, _ = w.Write([]byte("test"))
    })

    ts := httptest.NewServer(r)
    defer ts.Close()

    if resp, body := testRequest(t, ts, "GET", "/", nil); body != "root" && resp.StatusCode != 200 {
        t.Fatalf(body)
    }
}

func testRequest(t *testing.T, ts *httptest.Server, method, path string, body io.Reader) (*http.Response, string) {
    req, err := http.NewRequest(method, ts.URL+path, body)
    if err != nil {
        t.Fatal(err)
        return nil, ""
    }

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        t.Fatal(err)
        return nil, ""
    }

    respBody, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        t.Fatal(err)
        return nil, ""
    }
    defer resp.Body.Close()

    return resp, string(respBody)
}


推荐阅读