Isolation ohne Schmerz: Mock und Fixtures in Go-Tests

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Wenn die Realität stört: Warum brauchen wir Mocks und Fixtures in Go?

\n\n

Stellen Sie sich vor, Sie testen eine Funktion, die eine E-Mail-Benachrichtigung sendet. Jeder Testlauf ist eine echte E-Mail im Posteingang. Nach zehn Tests ist Ihr Postfach voll und Ihre Kollegen verfluchen den Spam. Oder schlimmer: Die Funktion greift auf eine externe API zu, die kostenpflichtig ist oder nur einmal am Tag läuft.

\n\n

In der Welt von Go (oder Golang, wie es oft genannt wird) ist Testen nicht nur ein Häkchen auf der Checkliste. Es ist das Fundament der Zuverlässigkeit. Damit Tests jedoch schnell und unabhängig sind, müssen wir den Code von der Außenwelt isolieren. Genau hier kommen Mock-Objekte (Mocks) und Fixtures ins Spiel.

\n\n

In diesem Artikel werden wir uns ansehen, wie man Abhängigkeiten richtig ersetzt (mockt) und Daten (Fixtures) in Go vorbereitet. Sie erfahren, wie Sie Tests schreiben, die nicht aufgrund von Netzwerk, Datenbank oder Tageszeit fehlschlagen. Los geht's!

\n\n

Was sind Mock und Fixture im Kontext von Go?

\n\n

Mock-Objekte: Stellvertreter für komplexe Systeme

\n\n

Mock-Objekte sind programmatische "Platzhalter", die das Verhalten realer Komponenten nachahmen. Anstatt eine echte Datenbank oder einen HTTP-Dienst aufzurufen, setzen wir ein Objekt ein, das vordefinierte Antworten zurückgibt.

\n\n

In Go sind Mocks besonders wichtig, da die Sprache die Arbeit mit Interfaces fördert. Wenn Ihr Code von einem Interface abhängt, können Sie die Implementierung leicht durch eine Testimplementierung ersetzen.

\n\n

Fixtures: Die Bühne bereiten

\n\n

Fixtures sind Daten oder Zustände, die vor Beginn eines Tests eingerichtet werden müssen. Zum Beispiel das Erstellen einer temporären Datenbank, das Befüllen mit Testdatensätzen oder das Konfigurieren des Dateisystems.

\n\n

Im Gegensatz zu Mocks, die das Verhalten ersetzen, bereiten Fixtures die Umgebung vor. Sie beantworten die Frage: "Was muss bereit sein, damit der Test starten kann?"

\n\n

Mocks in Go schreiben: Vom Einfachen zum Komplexen

\n\n

Der einfachste Weg: Manuelle Implementierung eines Interfaces

\n\n

Go erfordert keine speziellen Bibliotheken zum Erstellen von Mocks. Wenn Sie ein Interface haben, können Sie dessen Testimplementierung manuell schreiben. Dies ist ideal für kleine Projekte.

\n\n

Angenommen, wir haben ein Interface zum Senden von Benachrichtigungen:

\n\n
package notifier\n\ntype Notifier interface {\n    Send(to string, message string) error\n}\n\n// Echte Implementierung (nicht für Tests)\ntype EmailNotifier struct{}\n\nfunc (e *EmailNotifier) Send(to string, message string) error {\n    // Echte E-Mail senden\n    return nil\n}
\n\n

In der Testdatei erstellen wir einen Mock:

\n\n
package notifier\n\nimport "testing"\n\ntype MockNotifier struct {\n    Called bool\n    LastTo string\n    LastMsg string\n}\n\nfunc (m *MockNotifier) Send(to string, msg string) error {\n    m.Called = true\n    m.LastTo = to\n    m.LastMsg = msg\n    return nil\n}\n\nfunc TestSendAlert(t *testing.T) {\n    mock := &MockNotifier{}\n    // Verwenden des Mocks in einer Funktion, die Notifier akzeptiert\n    SendAlert(mock, "user@test.com", "Hello!")\n    \n    if !mock.Called {\n        t.Error("Methode Send wurde nicht aufgerufen")\n    }\n    if mock.LastTo != "user@test.com" {\n        t.Errorf("Falscher Empfänger: %s", mock.LastTo)\n    }\n}
\n\n

Vorteile: Volle Kontrolle, keine Abhängigkeiten.
\nNachteile: Viel Boilerplate-Code für komplexe Interfaces.

\n\n

Verwendung von testify/mock: Leistungsstark und bequem

\n\n

Die Bibliothek testify ist der De-facto-Standard für Mocks in Go. Sie bietet ein flexibles Framework zum Erstellen von Mocks mit Überprüfung von Argumenten und Aufrufanzahlen.

\n\n

Installation:

\n
go get github.com/stretchr/testify
\n\n

Beispiel mit testify/mock:

\n\n
package user\n\nimport (\n    "testing"\n    "github.com/stretchr/testify/mock"\n)\n\n// Interface definieren\ntype UserRepository interface {\n    GetUser(id int) (string, error)\n}\n\n// Mock-Struktur erstellen\ntype                

Blogs

Buchempfehlungen