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.
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
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!