深入了解gomock

一、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

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
VMXZ的頭像VMXZ
上一篇 2024-10-04 00:16
下一篇 2024-10-04 00:16

相關推薦

  • 深入解析Vue3 defineExpose

    Vue 3在開發過程中引入了新的API `defineExpose`。在以前的版本中,我們經常使用 `$attrs` 和` $listeners` 實現父組件與子組件之間的通信,但…

    編程 2025-04-25
  • 深入理解byte轉int

    一、位元組與比特 在討論byte轉int之前,我們需要了解位元組和比特的概念。位元組是計算機存儲單位的一種,通常表示8個比特(bit),即1位元組=8比特。比特是計算機中最小的數據單位,是…

    編程 2025-04-25
  • 深入理解Flutter StreamBuilder

    一、什麼是Flutter StreamBuilder? Flutter StreamBuilder是Flutter框架中的一個內置小部件,它可以監測數據流(Stream)中數據的變…

    編程 2025-04-25
  • 深入探討OpenCV版本

    OpenCV是一個用於計算機視覺應用程序的開源庫。它是由英特爾公司創建的,現已由Willow Garage管理。OpenCV旨在提供一個易於使用的計算機視覺和機器學習基礎架構,以實…

    編程 2025-04-25
  • 深入了解scala-maven-plugin

    一、簡介 Scala-maven-plugin 是一個創造和管理 Scala 項目的maven插件,它可以自動生成基本項目結構、依賴配置、Scala文件等。使用它可以使我們專註於代…

    編程 2025-04-25
  • 深入了解LaTeX的腳註(latexfootnote)

    一、基本介紹 LaTeX作為一種排版軟體,具有各種各樣的功能,其中腳註(footnote)是一個十分重要的功能之一。在LaTeX中,腳註是用命令latexfootnote來實現的。…

    編程 2025-04-25
  • 深入理解Python字元串r

    一、r字元串的基本概念 r字元串(raw字元串)是指在Python中,以字母r為前綴的字元串。r字元串中的反斜杠(\)不會被轉義,而是被當作普通字元處理,這使得r字元串可以非常方便…

    編程 2025-04-25
  • 深入剖析MapStruct未生成實現類問題

    一、MapStruct簡介 MapStruct是一個Java bean映射器,它通過註解和代碼生成來在Java bean之間轉換成本類代碼,實現類型安全,簡單而不失靈活。 作為一個…

    編程 2025-04-25
  • 深入探討馮諾依曼原理

    一、原理概述 馮諾依曼原理,又稱「存儲程序控制原理」,是指計算機的程序和數據都存儲在同一個存儲器中,並且通過一個統一的匯流排來傳輸數據。這個原理的提出,是計算機科學發展中的重大進展,…

    編程 2025-04-25
  • 深入了解Python包

    一、包的概念 Python中一個程序就是一個模塊,而一個模塊可以引入另一個模塊,這樣就形成了包。包就是有多個模塊組成的一個大模塊,也可以看做是一個文件夾。包可以有效地組織代碼和數據…

    編程 2025-04-25

發表回復

登錄後才能評論