Rumah >pembangunan bahagian belakang >Golang >Bagaimana untuk menggunakan suntikan pergantungan untuk ujian unit di Golang?

Bagaimana untuk menggunakan suntikan pergantungan untuk ujian unit di Golang?

WBOY
WBOYasal
2024-06-02 20:41:00808semak imbas

Menggunakan suntikan kebergantungan (DI) dalam ujian unit Golang boleh mengasingkan kod untuk diuji dan memudahkan persediaan dan penyelenggaraan ujian. Perpustakaan DI yang popular termasuk wayar dan go-inject, yang boleh menjana stub pergantungan atau ejekan untuk ujian. Langkah-langkah ujian DI termasuk menyediakan kebergantungan, menyediakan kes ujian dan menegaskan keputusan. Contoh penggunaan DI untuk menguji fungsi pengendalian permintaan HTTP menunjukkan betapa mudahnya untuk mengasingkan dan menguji kod tanpa kebergantungan atau komunikasi sebenar.

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

Cara menggunakan suntikan kebergantungan untuk ujian unit di Golang

Suntikan ketergantungan (DI) ialah corak reka bentuk yang membolehkan anda menyediakan objek dengan kebergantungannya tanpa menciptanya secara eksplisit. Dalam ujian unit, DI boleh membantu anda mengasingkan kod yang ingin anda uji dan menjadikan ujian lebih mudah untuk disediakan dan diselenggara.

DI di Golang

Terdapat banyak perpustakaan DI yang popular di Golang, yang paling terkenal ialah [wire](https://github.com/google/wire) dan [go-inject](https:/ /github.com/go-inject/go-inject). Perpustakaan ini berfungsi dengan menghasilkan stub atau olok-olok yang boleh digunakan sebagai kebergantungan dalam ujian.

Sediakan ujian DI

Begini cara menyediakan ujian unit DI menggunakan wayar:

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)
            }
        })
    }
}

Menggunakan DI untuk ujian

Dalam ujian di atas, kami menggunakan wire.Build untuk jana Instance struktur Field yang mengandungi stub pergantungan untuk digunakan untuk ujian. Kami kemudiannya boleh menyediakan kes ujian dan menegaskan keputusan seperti biasa. 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

🎜Kes Praktikal🎜🎜🎜Begini cara menggunakan DI untuk menguji unit fungsi yang mengendalikan permintaan HTTP: 🎜rrreee🎜Dengan menggunakan DI dan stub, kami dapat mengasingkan dan menguji fungsi GetUser dengan mudah tanpa perlu Melibatkan pangkalan data sebenar atau permintaan HTTP. 🎜

Atas ialah kandungan terperinci Bagaimana untuk menggunakan suntikan pergantungan untuk ujian unit di Golang?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn