Integrationstest für Apache Kafka in Go schreiben

Integrationstest für Apache Kafka in Go schreiben

Die Bedeutung von Integrationstests in der Welt der Softwareentwicklung kann nicht genug betont werden. Insbesondere in der Programmiersprache Go/Golang, wenn es darum geht, eine nahtlose Anbindung an Apache Kafka mit der conluent-kafka-go Bibliothek zu gewährleisten.

In diesem Artikel wird gezeigt wie man mit Hilfe eines von der conluent-kafka-go Bibliothek zur Verfügung gestellten Mock-Clusters Integrationstests für Apache Kafka schreiben kann. Diese können ohne Probleme in einer Build-Pipeline ausgeführt werden, ohne dass eine Apache Kafka Instanz benötigt wird.

Folgende Ziele sollen beim Testen erreicht werden:

  • Tests sollen in einer CI/CD-Pipeline “autark” ausgeführt werden können. Mehrere Tests sollen parallel ausgeführt werden können ohne dass diese sich gegenseitig beeinflussen.

  • Wenig Ressourcenbedarf beim Testablauf.

  • Schnelle Durchlaufgeschwindigkeit.

Apache Kafka

In vielen geschäftskritischen Anwendungen wird Apache-Kafka für die Kommunikation bzw. den Austausch von Datenströmen zwischen mehreren unabhängigen Microservices eingesetzt. Kern eines Kafka-Clusters sind sogenannte Message-Broker, die diese Daten speichern und entsprechend an Konsumenten oder Consumer weitergeben. Nachrichten-Producer erzeugen die Datenströme in Form von Nachrichten, den sogenannten Messages.

Apache Kafka Communication

Apache Kafka Communication

Das Messaging-Pattern beschreibt z. B. die Einsatz eines Message-Brokers innerhalb von Anwendungen für die asynchrone Kommunikation.

Warum confluent-kafka-go

Kafka besitzt für die Kommunikation eine API, die nicht nur von Java (Apache-Kafka ist selbst in Java implementiert) aus, sondern auch von vielen weiteren Programmiersprachen angesprochen werden kann. Der Zugriff auf Apache Kafka mittels Go erfolgt analog über eine entsprechende Client-Bibliothek. Mehrere Varianten stehen hier zur Verfügung und bieten unterschiedliche Vor- und Nachteile:

In diesem Artikel wird mit der conluent-kafka-go Bibliothek gearbeitet, die von Confluent Inc. entwickelt wurde und als Open-Source bei GitHub zur Verfügung steht. Sie basiert auf der librdkafka C-Bibliothek, die ebenfalls in anderen Programmiersprachen als Basis für eine Anbindung an Apache Kafka eingesetzt wird.

Der große Vorteil eines Einsatz liegt sicher in der Stabilität und Reife der Implementierung. Confluent ist das Unternehmen, das Kafka unterstützt und erweitert. Die Verwendung der von Confluent bereitgestellten Client-Bibliothek gewährleistet eine hohe Qualität und Zuverlässigkeit, da sie direkt von den Experten entwickelt und gewartet wird.

Zusätzlich ist die Bibliothek darauf ausgerichtet, eine hohe Leistung zu bieten und effizient mit Kafka-Clustern kommunizieren.

Neben den wichtigen Punkten für einen effektiven Einsatz in der Produktion bietet die Bibliothek ebenfalls einen sogenannten Mock-Cluster, der speziell für den Einsatz in Integrationstests entwickelt wurde.

Wenn eine leistungsstarke Messaging-Lösung für Go-Anwendungen benötigt wird, ist die Kombintation aus Apache Kafka und dieser Bibliothek sicher eine gute Wahl.

Kafka Consumer in Go - Beispiel

Für das Beispiel wird davon ausgegangen, dass bereits zwei Funktionen für das Senden (Produce) und Empfangen (Consumer) von Nachrichten über Kafka implementiert sind. Beide Funktionen erhalten den string der BootstrapServers als Parameter übergeben.

An dieser Stelle kommt nun der Mock-Server zum Einsatz. Dieser lässt sich mit folgendem Aufruf starten:

cluster, err := kafka.NewMockCluster(1)

Anschließend kann man den dynamischen Port, der für die Kommunikation verwendet wird, auslesen und als Parameter für Consumer und Producer nutzen: Z. B. so:

Produce(cluster.BootstrapServers(), testMessage)

In einem gesamten Beispiel lässt sich das wie Folgt verwenden:

package kafkaintegrationtest

import (
	"github.com/confluentinc/confluent-kafka-go/v2/kafka"
	"testing"
)

func TestKafka(t *testing.T) {

	//given
	testMessage := "Hello World"
	cluster, err := kafka.NewMockCluster(1)
	if err != nil {
		t.Errorf("could not start cluster: %v", err)
		return
	}

	//when
	go func() {
		err := Produce(cluster.BootstrapServers(), testMessage)
		if err != nil {
			t.Errorf("could not produce message: %v", err)
			return
		}
	}()

	message, err := Consumer(cluster.BootstrapServers())
	if err != nil {
		t.Errorf("could not consume message: %v", err)
		return
	}

	//then
	if message != testMessage {
		t.Errorf("wrong message received: %s", message)
	}

}

Mit diesem Ansatz lassen sich leicht weitere Tests schreiben, die eventuell auch besser wie in diesem Beispiel synchronisiert sind.

Mockserver

Der Mock-Server bietet noch weitere Möglichkeiten. So können auch Fehlerfälle simuliert werden. Die komplette API findet man bei GitHub.

Fazit

Mit Hilfe des Mock-Servers der Bibliothek lassen sich praxisnahe Integrationstests implementieren, die möglichst nahe an der Produktionsumgebung sind, da sie über Remote-Schnittstellen kommunizieren und die echte Implementierung nutzen.

Zum Testen wird in diesem Beispiel kein eigener Kafka Server benötigt und trotzdem wird über die “echten” Schnittstellen kommuniziert.

Das komplette Beispiel kann auch in GitHub gefunden werden.

16.11.2023

 

Kennen Sie schon das Buch zum Thema?

Der praktische Soforteinstieg für Developer und Softwarearchitekten, die direkt mit Go produktiv werden wollen.

  • Von den Sprachgrundlagen bis zur Qualitätssicherung
  • Architekturstil verstehen und direkt anwenden
  • Idiomatic Go, gRPC, Go Cloud Development Kit
  • Cloud-native Anwendungen erstellen
Microservices mit Go Buch

zur Buchseite beim Rheinwerk Verlag Rheinwerk Computing, ISBN 978-3-8362-7559-0 (als PDF, EPUB, MOBI und Papier)

Kontakt

Source Fellows GmbH

Source Fellows GmbH Logo

Lerchenstraße 31

72762 Reutlingen

Telefon: (0049) 07121 6969 802

E-Mail: info@source-fellows.com