一、gomock概述
gomock是Go語言開發的mock框架,用來模擬介面和函數的調用。模擬是測試的關鍵,利用gomock可以快速創建一個虛擬實例來充當一個介面或對象的預期實例,並進行完全控制。
通常,在執行測試時,我們需要創建不同的對象或傳遞處理流程中的值,而在這些對象或值的基礎上構建預期的行為,這就是mocking的目標。gomock幫助我們通過聲明的方式來創建方法和函數的mock版本,使得我們充分控制mock的實現,從而讓我們的測試更加可控。
在模擬測試中,gomock有許多非常好用的功能,例如,將需要模擬的對象注入到被測試對象中,從而使被測試對象執行預期行為。同時,gomock支持鏈式調用,可以根據需求進行代碼優化。
二、gomock gomonkey
gomock gomonkey是gomock功能的補充,是一個用於動態修改函數的庫。gomock gomonkey使用了codegen技術,通過解析代碼文件生成原始函數的交換代碼,而不是運行時的重載代碼。因此,它比直接使用reflect和unsafe包來修改代碼更加安全和可控。
gomock gomonkey提供了幾個函數來替換需要測試的函數,例如:gomock.ApplyFunc、gomock.ApplyMethod、gomock.ApplyGlobalVar等等。代碼示例如下:
// 原始函數 func Divide(a, b int) (int, error) { if b == 0 { return 0, errors.New("division by zero") } return a / b, nil } // 測試函數 func TestDivide(t *testing.T) { patch := gomonkey.ApplyFunc(Divide, func(a, b int) (int, error) { return 0, errors.New("mock error") }) defer patch.Reset() _, err := Divide(1, 0) assert.NotNil(t, err) }
通過ApplyFunc,我們可以針對Divide函數進行mock,讓其返回一個錯誤信息,快速進行異常測試。
三、gomock sql queryerror
在使用gomock進行測試時,我們需要模擬資料庫操作,而模擬SQL操作是測試中的一項重要的工作,gomock提供了針對SQL的模擬功能。
gomock sql queryerror是一個提供了模擬SQL查詢錯誤的框架。在執行SQL查詢操作時,資料庫可能會返回各種不同類型的錯誤,例如:未知的列、空引用、無法連接、死鎖,等等。這時,我們需要創建一個模擬類來進行測試。gomock sql queryerror提供了一個sql.DB介面,支持sql.Open、Prepare和Query三個基本函數,如下:
// 原始函數 func QueryByID(db *sql.DB, id int) (*User, error) { row := db.QueryRow("SELECT * FROM users WHERE id = ?", id) user := User{} err := row.Scan(&user.ID, &user.Name, &user.Age) if err != nil { return nil, err } return &user, nil } // 測試函數 func TestQueryByID(t *testing.T) { db, mock, err := sqlmock.New() if err != nil { t.Fatalf("error creating mock database: %s", err) } defer db.Close() rows := sqlmock.NewRows([]string{"id", "name", "age"}). AddRow(1, "testuser", 20) mock.ExpectPrepare("SELECT * FROM users WHERE id = ?") mock.ExpectQuery("SELECT * FROM users WHERE id = ?").WithArgs(1).WillReturnRows(rows) user, err := QueryByID(db, 1) assert.Nil(t, err) assert.NotNil(t, user) }
這裡,我們使用了gomock sql queryerror來構建一個模型,用來模擬SQL查詢。在進行測試時,我們可以通過這個模型來執行預期的SQL查詢,並且可以模擬各種類型的錯誤,從而保證應用程序的健壯性。
四、gomock doandreturn
gomock doandreturn是gomock的另一個重要的特性,可以用來打樁。在編寫測試時,我們經常需要模擬不同的返回值或異常,但有時候難以模擬或判斷所有情況,gomock doandreturn為我們提供了一種靈活的方式來處理這些問題。
我們可以使用gomock doandreturn來替換需要mock的函數,這樣做的好處是可以在函數執行之前、之後觸發自定義的條件,例如:返回值、異常、計數等等。代碼示例如下:
// 原始函數 type MyService struct{} func (s *MyService) Action() (int, error) { fmt.Println("step 1") ret, err := s.Step2() fmt.Println("step 3") if err != nil { return 0, err } return ret, nil } func (s *MyService) Step2() (int, error) { fmt.Println("step 2") return 100, nil } // 測試函數 func TestAction(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() mock := NewMockMyService(ctrl) mock.EXPECT().Step2().Return(200, nil) mock.EXPECT().Step2().DoAndReturn(func() (int, error) { fmt.Println("fake step 2") return 200, nil }) _, _ = mock.Action() }
這裡,我們使用gomock doandreturn來測試MyService函數的Action方法。通過替換Step2函數,我們可以測試Step2函數的返回值,並添加一個返回值為200的方法,從而模擬一個假的返回值。這樣,我們就可以針對具體情況進行測試,並可以實現更加精準的結果。
五、gomock打樁
gomock打樁是將gomock用於單元測試的核心特性之一。打樁可以讓我們更好地模擬系統的各種類型和狀態,在實際的單元測試中使用gomock打樁可以極大地簡化測試的工作。
gomock打樁的方法主要有3種,分別是EXPECT、ANY和AnyTimes:
- EXPECT:使用該方法可以規定方法被調用的精確次數。方法調用次數不與預期次數相符時,會觸發panic。
- ANY:無論調用次數,該方法都會按預期返回結果,可以用於模擬返回值。
- AnyTimes:該方法只規定方法被調用的最少次數,且不會對方法調用次數做出強制要求,可以用於模擬不同次數的調用。
代碼示例如下:
// 原始函數 type MyService struct{} func (s *MyService) DoSmth(r *http.Request, writer http.ResponseWriter) { id := r.URL.Query().Get("id") if id == "" { return } writer.WriteHeader(http.StatusOK) writer.Write([]byte("success")) } // 測試函數 func TestMyService(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() req, _ := http.NewRequest("GET", "/test?id=1", nil) recorder := httptest.NewRecorder() mock := NewMockMyService(ctrl) mock.EXPECT().DoSmth(req, recorder).Times(2) mock.DoSmth(req, recorder) mock.DoSmth(req, recorder) }
通過上述代碼,我們創建了一個DoSmth函數用於測試,利用gomock打樁的EXPECT方法規定函數被調用的精確次數為2。在測試時,我們進行了2次調用,從而通過單元測試來判斷是否符合預期。
總結
gomock是一個非常強大的mock框架,通過簡潔的代碼和方便的API,可以讓我們輕鬆地實現單元測試。在本文中,我們介紹了gomock的幾個重要的特性,包括gospy、gomock gomonkey、gomock sql queryerror、gomock doandreturn和打樁。通過這些特性,我們可以更加自由地控制mock,並制定更精確的單元測試策略。
原創文章,作者:VMXZ,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/136484.html