Testing mit GoMock: Ein Tutorial

Testing mit GoMock: Ein Tutorial

Willkommen zu unserem Tutorial über das Testen von Code mit der GoMock-Mocking-Bibliothek und dem standardmäßigen Testpaket von Go.

GoMock ist ein Mock-Framework für Go. Es hat einen gewissen offiziellen Status als Teil der github.com/golang-Organisation, integriert sich gut mit dem eigenen Testing-Paket und bietet eine flexible Expectation-API.

In diesem Tutorial werden wir Schritt für Schritt durchgehen, wie man mit GoMock testet. Wir werden uns die Installation, die grundlegende Verwendung, die Verwendung von GoMock mit go:generate, die Verwendung von Argument-Matchern, die Überprüfung der Aufrufreihenfolge und die Angabe von Mock-Aktionen ansehen.

Bevor wir beginnen, stellen Sie sicher, dass Sie die GoMock-Pakete (github.com/golang/mock/gomock) und das Code-Generierungstool mockgen (github.com/golang/mock/mockgen) installiert haben.

Inhaltsverzeichnis

  • Installation
  • Grundlegende Verwendung
  • Verwendung von GoMock mit go:generate
  • Verwendung von Argument-Matchern
  • Überprüfen der Aufrufreihenfolge
  • Festlegen von Mock-Aktionen
  • Zusammenfassung

Installation

In diesem Abschnitt zeigen wir Ihnen, wie Sie GoMock installieren können.

Zuerst müssen wir das Paket “gomock” und das Code-Generierungstool “mockgen” installieren. Beide Pakete können mit dem Befehl “go get” installiert werden:

go get github.com/golang/mock/gomock
go get github.com/golang/mock/mockgen

Wenn die Installation erfolgreich war, können Sie überprüfen, ob das “mockgen”-Binärprogramm erfolgreich installiert wurde, indem Sie den folgenden Befehl ausführen:

mockgen -h

Wenn Sie keine Fehlermeldung erhalten und eine Liste der verfügbaren Flags angezeigt wird, ist die Installation abgeschlossen und Sie können mit dem Testen Ihres Codes beginnen!

Grundlegende Verwendung

Die Verwendung von GoMock umfasst vier grundlegende Schritte:

  1. Verwenden Sie “mockgen”, um ein Mock-Objekt für das zu mockende Interface zu generieren.
  2. Erstellen Sie in Ihrem Test eine Instanz von “gomock.Controller” und übergeben Sie sie dem Konstruktor des Mock-Objekts, um ein Mock-Objekt zu erhalten.
  3. Verwenden Sie “EXPECT()” auf Ihren Mocks, um ihre Erwartungen und Rückgabewerte festzulegen.
  4. Rufen Sie “Finish()” auf dem Mock-Controller auf, um die Erwartungen des Mocks zu überprüfen.
LESEN  Dororo: Eine faszinierende Geschichte über Tapferkeit und das Überwinden von Dämonen

Lassen Sie uns ein kleines Beispiel betrachten, um den obigen Ablauf zu veranschaulichen. Wir betrachten zwei Dateien – ein Interface “Doer” in der Datei “doer/doer.go”, das wir mocken möchten, und eine Struktur “User” in “user/user.go”, die das “Doer”-Interface verwendet.

Die Schnittstelle, die wir mocken möchten, ist recht einfach – sie hat eine einzige Methode “DoSomething”, die etwas mit einer Zahl und einem String macht und einen Fehler zurückgibt.

Der Code, den wir testen möchten, sieht wie folgt aus (beachten Sie, dass dies nur ein Beispiel ist und der tatsächliche Code möglicherweise anders aussieht):

package user

import (
    "fmt"

    "github.com/sgreben/testing-with-gomock/doer"
)

type User struct {
    Doer doer.Doer
}

func (u *User) Use() error {
    err := u.Doer.DoSomething(123, "Hello GoMock")
    if err != nil {
        return fmt.Errorf("error from DoSomething: %w", err)
    }
    return nil
}

Um diesen Code zu testen und das “Doer”-Interface zu mocken, müssen wir die “mockgen”-Befehl nutzen.

Hier ist, wie wir es tun können:

mockgen -destination=mocks/mock_doer.go -package=mocks github.com/sgreben/testing-with-gomock/doer Doer

Wir erstellen zuerst ein Verzeichnis “mocks”, das unsere Mock-Implementierungen enthält, und führen dann den “mockgen”-Befehl für das “doer”-Paket aus. Der oben genannte Befehl generiert ein Mock-Objekt mit dem Namen “mockDoer” im Paket “mocks”.

Der generierte Code wird in “mocks/mock_doer.go” gespeichert. Hier sehen Sie, wie ein beispielhafter generierter Mock für das “Doer”-Interface aussehen könnte:

package mocks

import (
    "github.com/golang/mock/gomock"
)

// MockDoer is a mock implementation for the Doer interface.
type MockDoer struct {
    ctrl     *gomock.Controller
    recorder *MockDoerMockRecorder
}

// MockDoerMockRecorder is the mock recorder for MockDoer.
type MockDoerMockRecorder struct {
    mock *MockDoer
}

// NewMockDoer creates a new mock instance.
func NewMockDoer(ctrl *gomock.Controller) *MockDoer {
    mock := &MockDoer{ctrl: ctrl}
    mock.recorder = &MockDoerMockRecorder{mock}
    return mock
}

// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockDoer) EXPECT() *MockDoerMockRecorder {
    return m.recorder
}

// DoSomething mocks the DoSomething method of the Doer interface.
func (m *MockDoer) DoSomething(arg1 int, arg2 string) error {
    m.ctrl.T.Helper()
    ret := m.ctrl.Call(m, "DoSomething", arg1, arg2)
    ret0, _ := ret[0].(error)
    return ret0
}

Sie können sehen, dass der generierte Mock eine Methode “EXPECT()” enthält, mit der Sie die Erwartungen für den Mock festlegen können.

LESEN  Die Abgasrückführung: Wie Delphi-AGR-Ventile den Unterschied machen

Nun können Sie Ihren Test schreiben, indem Sie das generierte Mock-Objekt verwenden:

package user_test

import (
    "testing"

    "github.com/golang/mock/gomock"
    "github.com/stretchr/testify/assert"

    "github.com/sgreben/testing-with-gomock/mocks"
    "github.com/sgreben/testing-with-gomock/user"
)

func TestUser_Use(t *testing.T) {
    ctrl := gomock.NewController(t)
    defer ctrl.Finish()

    mockDoer := mocks.NewMockDoer(ctrl)
    mockDoer.EXPECT().DoSomething(123, "Hello GoMock").Return(nil)

    u := user.User{
        Doer: mockDoer,
    }
    err := u.Use()

    assert.NoError(t, err)
    mockDoer.EXPECT().DoSomething(123, "Hello GoMock").Return(fmt.Errorf("some error"))
    err = u.Use()
    assert.Error(t, err)
}

In diesem Beispiel haben wir eine Testfunktion TestUser_Use geschrieben, die den Test für die Use-Methode der User-Struktur enthält.

Wir erstellen einen Mock-Controller mit gomock.NewController und verwenden ihn, um ein Mock-Objekt für das Doer-Interface zu erstellen. Dann setzen wir unsere Erwartung für den Mock-Call, indem wir EXPECT().DoSomething(123, "Hello GoMock").Return(nil) aufrufen. Schließlich erstellen wir eine Instanz von User, die das Mock-Objekt verwendet, und rufen die Use-Methode auf. Wir überprüfen, ob kein Fehler aufgetreten ist.

Weitere Tests können für verschiedene Szenarien und Rückgabewerte durchgeführt werden.

Das war’s auch schon! Sie haben gelernt, wie man GoMock verwendet, um Code zu testen. Wir haben die Installation, die grundlegende Verwendung, die Verwendung mit go:generate, die Verwendung von Argument-Matchern, die Überprüfung der Aufrufreihenfolge und die Angabe von Mock-Aktionen behandelt.

Wenn Sie Fragen haben oder etwas unklar ist, lassen Sie es mich bitte in den Kommentaren wissen!