首頁 > 後端開發 > Golang > 主體

如何在 Golang 中使用依賴注入進行單元測試?

WBOY
發布: 2024-06-02 20:41:00
原創
780 人瀏覽過

在 Golang 單元測試中使用依賴注入(DI)可以隔離要測試的程式碼,簡化測試設定和維護。流行的 DI 庫包括 wire 和 go-inject,它們可以產生依賴項樁或模擬,供測試使用。 DI 測試的步驟包括設定依賴項、設定測試案例和斷言結果。使用 DI 測試 HTTP 請求處理函數的範例表明,它可以輕鬆隔離和測試程式碼,無需實際依賴項或通訊。

如何在 Golang 中使用依赖注入进行单元测试?

如何在Golang 中使用依賴注入進行單元測試

##依賴注入(DI)是一種設計模式,它允許你向物件提供其依賴項,而無需明確地創建它們。在單元測試中,DI 可以幫助你隔離要測試的程式碼,並使測試更容易設定和維護。

Golang 中的DI

Golang 中有許多流行的DI 庫,其中最著名的是[wire](https://github.com/google/ wire) 和[go-inject](https://github.com/go-inject/go-inject)。這些庫的工作原理是產生可以用作測試中依賴項的樁或模擬。

設定DI 測試

以下是如何使用wire 設定DI 單元測試:

import (
    "context"
    "testing"

    "github.com/google/go-cmp/cmp"
)

// Interface we want to test.
type Greeter interface {
    Greet(ctx context.Context, name string) (string, error)
}

// Implementation we want to test.
type DefaultGreeter struct{}

func (g DefaultGreeter) Greet(ctx context.Context, name string) (string, error) {
    return "Hello, " + name, nil
}

func TestGreeter_Greet(t *testing.T) {
    type Fields struct {
        greeter Greeter
    }

    wire.Build(Fields{
        greeter: (*DefaultGreeter)(nil),
    })

    cases := []struct {
        setup    func(t *testing.T, fields Fields)
        expected *string
        wantErr  bool
    }{
        {
            expected: String("Hello, Bob"),
        },
    }

    for _, tc := range cases {
        tc := tc // capture range variable
        t.Run(testName, func(t *testing.T) {
            t.Parallel()

            fields := Fields{}
            tc.setup(t, fields)

            result, err := fields.greeter.Greet(context.Background(), "Bob")

            if (err != nil) != tc.wantErr {
                t.Fatalf("error = %v, wantErr = %v", err, tc.wantErr)
            }
            if tc.wantErr {
                return
            }
            if diff := cmp.Diff(*tc.expected, result); diff != "" {
                t.Fatalf("result mismatch (-want +got):\n%s", diff)
            }
        })
    }
}
登入後複製

使用DI 進行測試

#在上面的測試中,我們使用

wire.Build 來產生一個Fields 結構的實例,該實例包含要用於測試的依賴項樁。然後,我們可以像往常一樣設定測試案例並斷言結果。

實戰案例

以下是如何使用DI 單元測試一個處理HTTP 請求的函數:

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

    "github.com/gorilla/mux"
    "github.com/stretchr/testify/assert"

    "mypkg/handlers"
)

// Interface we want to test.
type UserService interface {
    GetUser(id int) (*User, error)
}

// Implementation we want to test.
type DefaultUserService struct{}

func (s DefaultUserService) GetUser(id int) (*User, error) {
    return &User{ID: id, Name: "Bob"}, nil
}

type Request struct {
    UserService UserService
}

func (r Request) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    id, err := strconv.Atoi(mux.Vars(req)["id"])
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    user, err := r.UserService.GetUser(id)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    fmt.Fprintf(w, "%s", user.Name)
}

func TestHandler_GetUser(t *testing.T) {
    r := &Request{}

    type Fields struct {
        userService UserService
    }

    wire.Build(Fields{
        userService: (*DefaultUserService)(nil),
    })

    cases := []struct {
        name string
        id   int
        body string
        want string
    }{
        {
            body: `{"body":""}`,
            want: `Bob`,
        },
        {
            id:   2,
            body: `{"body":""}`,
            want: `Bob`,
        },
    }

    for _, tc := range cases {
        tc := tc // capture range variable
        t.Run(tc.name, func(t *testing.T) {
            req, _ := http.NewRequest("GET", "/", bytes.NewBuffer([]byte(tc.body)))
            if tc.id != 0 {
                req = mux.SetURLVars(req, map[string]string{"id": strconv.Itoa(tc.id)})
            }
            rr := httptest.NewRecorder()
            handler := http.HandlerFunc(r.ServeHTTP)
            handler.ServeHTTP(rr, req)

            assert.Equal(t, tc.want, rr.Body.String())
        })
    }
}
登入後複製

透過使用DI 和樁,我們能夠輕鬆地隔離和測試

GetUser 函數,而無需涉及實際的資料庫或HTTP 請求。

以上是如何在 Golang 中使用依賴注入進行單元測試?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板