Heim > Artikel > Backend-Entwicklung > Wie verwende ich die Abhängigkeitsinjektion für Unit-Tests in Golang?
Die Verwendung der Abhängigkeitsinjektion (DI) beim Golang-Unit-Testen kann den zu testenden Code isolieren und die Testeinrichtung und -wartung vereinfachen. Zu den beliebten DI-Bibliotheken gehören Wire und Go-Inject, die Abhängigkeits-Stubs oder Mocks zum Testen generieren können. Zu den Schritten des DI-Tests gehören das Einrichten von Abhängigkeiten, das Einrichten von Testfällen und das Durchführen von Ergebnissen. Ein Beispiel für die Verwendung von DI zum Testen einer HTTP-Anforderungsverarbeitungsfunktion zeigt, wie einfach es ist, Code ohne tatsächliche Abhängigkeiten oder Kommunikation zu isolieren und zu testen.
So verwenden Sie die Abhängigkeitsinjektion für Unit-Tests in Golang
Abhängigkeitsinjektion (DI) ist ein Entwurfsmuster, das es Ihnen ermöglicht, einem Objekt seine Abhängigkeiten bereitzustellen, ohne diese explizit zu erstellen. Bei Unit-Tests kann DI Ihnen dabei helfen, den Code zu isolieren, den Sie testen möchten, und Tests einfacher einzurichten und zu warten.
DI in Golang
Es gibt viele beliebte DI-Bibliotheken in Golang, die bekanntesten davon sind [wire](https://github.com/google/wire) und [go-inject](https:/ /github.com/go-inject/go-inject). Diese Bibliotheken funktionieren, indem sie Stubs oder Mocks generieren, die als Abhängigkeiten in Tests verwendet werden können.
DI-Tests einrichten
So richten Sie DI-Einheitentests mit Wire ein:
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 zum Testen verwenden
Im obigen Test verwenden wir wire.Build
, um generieren Eine Instanz einer Fields
-Struktur, die die Abhängigkeits-Stubs enthält, die zum Testen verwendet werden sollen. Anschließend können wir den Testfall aufbauen und die Ergebnisse wie gewohnt geltend machen. 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
einfach isolieren und testen ohne Beinhaltet tatsächliche Datenbank- oder HTTP-Anfragen. 🎜Das obige ist der detaillierte Inhalt vonWie verwende ich die Abhängigkeitsinjektion für Unit-Tests in Golang?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!