在 Golang 單元測試中使用依賴注入(DI)可以隔離要測試的程式碼,簡化測試設定和維護。流行的 DI 庫包括 wire 和 go-inject,它們可以產生依賴項樁或模擬,供測試使用。 DI 測試的步驟包括設定依賴項、設定測試案例和斷言結果。使用 DI 測試 HTTP 請求處理函數的範例表明,它可以輕鬆隔離和測試程式碼,無需實際依賴項或通訊。
如何在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()) }) } }
GetUser 函數,而無需涉及實際的資料庫或HTTP 請求。
以上是如何在 Golang 中使用依賴注入進行單元測試?的詳細內容。更多資訊請關注PHP中文網其他相關文章!