>  기사  >  백엔드 개발  >  Golang에서 단위 테스트에 종속성 주입을 사용하는 방법은 무엇입니까?

Golang에서 단위 테스트에 종속성 주입을 사용하는 방법은 무엇입니까?

WBOY
WBOY원래의
2024-06-02 20:41:00784검색

Golang 단위 테스트에서 DI(종속성 주입)를 사용하면 테스트할 코드를 격리하고 테스트 설정 및 유지 관리를 단순화할 수 있습니다. 널리 사용되는 DI 라이브러리에는 테스트용 종속성 스텁 또는 모의를 생성할 수 있는 wire 및 go-inject가 포함됩니다. DI 테스트 단계에는 종속성 설정, 테스트 사례 설정 및 결과 확인이 포함됩니다. DI를 사용하여 HTTP 요청 처리 기능을 테스트하는 예는 실제 종속성이나 통신 없이 코드를 격리하고 테스트하는 것이 얼마나 쉬운지 보여줍니다.

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

Golang에서 단위 테스트를 위해 종속성 주입을 사용하는 방법

종속성 주입(DI)은 명시적으로 종속성을 생성하지 않고도 개체에 종속성을 제공할 수 있는 디자인 패턴입니다. 단위 테스트에서 DI는 테스트하려는 코드를 격리하고 테스트를 더 쉽게 설정하고 유지 관리하는 데 도움이 될 수 있습니다.

DI in Golang

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 구조의 인스턴스입니다. 그런 다음 테스트 케이스를 설정하고 평소대로 결과를 어설션할 수 있습니다. 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

🎜실용 사례🎜🎜🎜다음은 DI를 사용하여 HTTP 요청을 처리하는 함수의 단위 테스트를 수행하는 방법입니다. 🎜rrreee🎜DI 및 스텁을 사용하면 GetUser 함수를 쉽게 격리하고 테스트할 수 있습니다. 실제 데이터베이스 또는 HTTP 요청과 관련됩니다. 🎜

위 내용은 Golang에서 단위 테스트에 종속성 주입을 사용하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.