Golang 단위 테스트에서 DI(종속성 주입)를 사용하면 테스트할 코드를 격리하고 테스트 설정 및 유지 관리를 단순화할 수 있습니다. 널리 사용되는 DI 라이브러리에는 테스트용 종속성 스텁 또는 모의를 생성할 수 있는 wire 및 go-inject가 포함됩니다. DI 테스트 단계에는 종속성 설정, 테스트 사례 설정 및 결과 확인이 포함됩니다. DI를 사용하여 HTTP 요청 처리 기능을 테스트하는 예는 실제 종속성이나 통신 없이 코드를 격리하고 테스트하는 것이 얼마나 쉬운지 보여줍니다.
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
GetUser
함수를 쉽게 격리하고 테스트할 수 있습니다. 실제 데이터베이스 또는 HTTP 요청과 관련됩니다. 🎜위 내용은 Golang에서 단위 테스트에 종속성 주입을 사용하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!