Heim  >  Artikel  >  Backend-Entwicklung  >  Mach dich lustig

Mach dich lustig

WBOY
WBOYOriginal
2024-07-31 09:16:32610Durchsuche

Go mock

Was ist Go-Mock?

Go Mock ist ein Mocking-Framework, das es Entwicklern ermöglicht, Scheinstrukturen für unsere Schnittstellen zu erstellen und deren Verhalten zu definieren.

Zum Beispiel kann es uns helfen, die Scheinimplementierungen für Repository zu generieren und die erwartete Ausgabe basierend auf den bestimmten Eingaben zu definieren.

Original-Repo: https://github.com/golang/mock

Jetzt wird es nicht mehr gepflegt, daher sollten wir stattdessen https://github.com/uber-go/mock verwenden.

Installation

go install go.uber.org/mock/mockgen@latest

Hauptmerkmale

  • Mock-Generierung: Gomock enthält ein Tool namens Mockgen, das automatisch Scheinimplementierungen von Schnittstellen generiert.
  • Flexible Erwartungen: Mit Gomock können Sie genaue Erwartungen an das Verhalten von Scheinobjekten definieren, wie zum Beispiel:
    • Die Argumente, die es erhalten sollte
    • Und die Werte, die zurückgegeben werden sollen
    • Spezifische Häufigkeit, minimale oder maximale Häufigkeit, mit der eine Methode aufgerufen werden soll

Mockgen-Befehl

Befolgen Sie dieses Dokument, um zu verstehen, wie Sie die Mockgen-CLI verwenden:

https://github.com/uber-go/mock?tab=readme-ov-file#running-mockgen

Verwendung

Angenommen, Sie haben eine IUserRepo-Schnittstelle mit einigen Methoden:

ports.go

package user

type IUserRepo interface {
    GetUserByID(id int) (*User, error)
    Insert(user User) error
    Update(id int, user User) error
}

domain.go

package user

type User struct {
    ID   int
    Name string
}

service.go

package user

import "fmt"

type UserService struct {
    repo IUserRepo
}

var invalidUserIDError = fmt.Errorf("invalid user id")

func (u *UserService) Upsert(user User) error {
    if user.ID <= 0 {
        return invalidUserIDError
    }
    existingUser, err := u.repo.GetUserByID(user.ID)
    if err != nil {
        return err
    }
    if existingUser == nil {
        return u.repo.Insert(user)
    }

    return u.repo.Update(user.ID, user)
}

1. Führen Sie „mockgen“ aus, um eine Scheininstanz zu generieren

go run go.uber.org/mock/mockgen@latest -source=interface.go -destination=mock.go -package=user
  • Quelle: Gibt die Datei an, die die Repository-Schnittstelle enthält.
  • Ziel: Gibt die Datei an, in die der generierte Mock-Code geschrieben wird.
  • Paket: Gibt den Paketnamen für den generierten Mock an.

2. Erwartungen angeben

service_test.go

package user

import (
    "go.uber.org/mock/gomock"
    "github.com/stretchr/testify/assert"
    "testing"
)

func TestUpsertUser(t *testing.T) {
    mockCtl := gomock.NewController(t)
    defer mockCtl.Finish()

    tests := []struct {
        name                 string
        user                 User
        specifyFunctionCalls func(mock *MockIUserRepo)
        expectedError        error
    }{
        {
            user: User{ID: 1, Name: "User 1"},
            name: "Should insert",
            specifyFunctionCalls: func(mockRepo *MockIUserRepo) {
                mockRepo.EXPECT().GetUserByID(1).Return(nil, nil).Times(1)
                mockRepo.EXPECT().Insert(User{ID: 1, Name: "User 1"}).Return(nil).Times(1)
            },
        },
        {
            name: "User existed - Should update",
            user: User{ID: 1, Name: "New User Name"},
            specifyFunctionCalls: func(mockRepo *MockIUserRepo) {
                mockRepo.EXPECT().GetUserByID(1).Return(&User{ID: 1, Name: "User 1"}, nil).Times(1)
                mockRepo.EXPECT().Update(1, User{ID: 1, Name: "New User Name"}).Return(nil).Times(1)
            },
        },
        {
            expectedError: invalidUserIDError,
        },
    }

    for _, test := range tests {
        t.Run(test.name, func(t *testing.T) {
            mockRepo := NewMockIUserRepo(mockCtl)
            if test.specifyFunctionCalls != nil {
                test.specifyFunctionCalls(mockRepo)
            }
            userService := UserService{repo: mockRepo}
            err := userService.Upsert(test.user)
            assert.Equal(t, test.expectedError, err)
        })
    }
}

In der Testdatei oben:

  • Mit „specifyFunctionCalls“ können wir die Scheinfunktionserwartung anpassen, welche Funktionen aufgerufen werden müssen und wie oft diese Funktionen aufgerufen werden müssen.
  • Wenn Sie versuchen, eine redundante Funktion zur Spezifikation „specifyFunctionCalls“ hinzuzufügen (z. B. durch Hinzufügen von „mockRepo.EXPECT().Update(....)“ im ersten Test), schlägt Ihr Test aufgrund des Fehlers „fehlende(r) Aufruf(e)“ fehl. .
  • Wenn Ihr Dienst eine Funktion aufruft, die nicht angegeben wurde, schlägt Ihr Test aufgrund des Fehlers fehl: Es gibt keine erwarteten Aufrufe der Methode „Insert“ für diesen Empfänger.

Quellcode

https://github.com/huantt/gomock-demo

Das obige ist der detaillierte Inhalt vonMach dich lustig. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Vorheriger Artikel:Unit-Test für unterwegsNächster Artikel:Unit-Test für unterwegs