Fake-Daten in Java mit Data Faker

30.06.2022

Als Entwickler gibt es viele Situationen, in denen man sich Testdaten überlegen muss. Beim automatischen Erstellen von solchen Fake-Daten hilft die Library „Data Faker“.

Problemstellung

Bei der Entwicklung von Software werden oft Testdaten benötigt. Zwei Beispiele dafür sind Daten für Unit-Tests und Fake-Daten in einer Entwicklungs-Datenbank. Oft verwendet man in solchen Fällen Namen wie „Max Mustermann“ oder einfach nur Attribute mit dem Wert „Test“. Als Folge daraus ergeben sich verschiedene Probleme. Einerseits werden Corner Cases, wie Umlaute in Namen, bei der Entwicklung nicht abgedeckt. Andererseits kann man die verschiedenen Objekte nicht mehr einfach voneinander unterscheiden. Anders gesprochen nimmt die Lesbarkeit bei schlechten Testdaten ab.

Data Faker

Um diesen Problemen zumindest teilweise Abhilfe zu verschaffen wurde die Library Data Faker entwickelt. Die Library ist eine Portierung einer bereits bestehenden Ruby-Library und ermöglicht es Fake-Daten für verschiedene Bereiche zu erstellen. 

Zu den typischen Bereichen zählen unter anderem Namen, Adressen, Firmen, Telefonnummern und Mailadressen. Neben diesen Daten gibt es aber auch die Möglichkeit, Daten wie IP-Adressen, MAC-Adressen oder Kreditkartennummern zu generieren. Die Daten stammen hierbei aus verschiedenen mitgelieferten Dateien. Hilfreich ist hierbei, dass es verschiedene Datensätze für verschiedene Länder gibt. So enthält der Datensatz für Deutschland auch Umlaute, sowie Adressen im deutschen Format.

Wie verwende ich die Library?

Zur Verwendung der Library muss folgende Maven Dependency hinzugefügt werden:

<dependency>
    <groupId>net.datafaker</groupId>
    <artifactId>datafaker</artifactId>
    <version>1.4.0</version>
</dependency>

Die Generierung der Daten erfolgt über eine Instanz des Faker-Objekts. Über den Konstruktur kann zudem ein Locale für das entsprechende Land mitgegeben werden, für das man die Daten generieren möchte:

Faker faker = new Faker(Locale.GERMAN);
Address address = faker.address();

System.out.println("Vorname: " + address.firstName());
System.out.println("Nachname: " + address.lastName());
System.out.println("Ort: " + address.city());
System.out.println("Straße: " + address.streetAddress());

----
Vorname: Charlotta
Nachname: Rohrer
Ort: Klein Phoebe
Straße: Wiehbachtal 98

Wird kein Locale angegeben, wird standardmäßig der US-Datensatz verwendet:

Vorname: Warren
Nachname: Bednar
Ort: North Brenton
Straße: 6763 Sandy Fields

Nachfolgend einige weitere Faker die besonders interessant sind:

Faker faker = new Faker(Locale.GERMAN);
Company company = faker.company();

System.out.println("Firma: " + company.name());
System.out.println("URL: " + company.url());
System.out.println("Industry: " + company.industry());

----
Firma: Eifert, Schieskow und Neupert
URL: www.dittmar-reinke.com
Industry: Internet
Faker faker = new Faker(Locale.GERMAN);
Internet internet = faker.internet();

System.out.println("Email: " + internet.emailAddress());
System.out.println("Domain: " + internet.domainName());
System.out.println("Ipv4: " + internet.ipV4Address());
System.out.println("MAC: " + internet.macAddress());
System.out.println("Password: " + internet.password());

----
Email: marieke.kuske@gmx.de
Domain: beutelspacher.info
Ipv4: 83.236.87.211
MAC: 8c:64:d0:b1:02:ae
Password: adrz96hrjlboocb

Komplexere Datengenerierung

Über die Collections-API kann man auch direkt eine Liste mit verschiedenen Werten erstellen. Dazu werden einer oder mehrere Supplier definiert, welche die Daten erstellen. Zudem kann eine Unter-/Obergrenze für die Größe der Liste definiert werden.

Faker faker = new Faker(Locale.GERMAN);
List<String> objects = faker.<String>collection()
 	.suppliers(
             () -> faker.name().firstName(),
             () -> faker.name().lastName())
        .minLen(1)
        .maxLen(5)
        .build().get();
objects.forEach(System.out::println);

----
Mirja
Bussmann

Es lassen sich aber nicht nur einzelne Attribute erstellen. Über sogenannte Expressions können auch komplexere Daten erstellt werden. Dazu gibt es unter anderem die Möglichkeit, Wildcards zu platzieren, um diese mit zufälligen Buchstaben oder Zahlen zu ersetzen. Eine weitere Möglichkeit ist die Angabe eines Regex. Hier erstellt der Faker einen Wert der dem Regex entspricht.

Faker faker = new Faker();
faker.expression("#{letterify 'prefix????suffix'}"); // prefixqwassuffix
faker.expression("#{numerify 'Name##'}"); // Name48
faker.expression("#{examplify 'Example'}"); // Mdhlggg
faker.expression("#{regexify '[a-z0-9]{4,10}'}"); // s45a

Weitere Beispiele finden sich auf der Dokumentationsseite.

Unit-Tests

Für Unit-Tests sind unter anderem die mit JUnit 5 eingeführten Parametrisierten Tests interessant. So kann man in einem Unit-Test einen Stream mit generierten Fake-Daten an eine Methode übergeben, um mit diesen dann den Testfall mehrfach durchzuführen. Beispielsweise kann man damit eigene Validierungen testen. Der Vorteil hierbei ist die Verwendung von unterschiedlichen Daten bei jedem Durchlauf.

@ParameterizedTest
@MethodSource("generateTestName")
public void nameShouldBeValid(String input, boolean expected)
{
	boolean actual = NameValidator.isValid(input);
        assertThat(actual).isEqualTo(expected);
}

private static Stream<Arguments> generateTestName() {
	Faker faker = new Faker();
	return IntStream.range(0, 10)
           	.mapToObj(i -> faker.address().firstName() + " " + faker.address().lastName())
                .map(name -> Arguments.of(name, true));
}

Abgesehen davon macht es aber auch allgemein Sinn Objekte in Unit-Tests mit Fake-Daten zu befüllen. Denn durch die realitätsnahen Werte ergeben sich bei fehlgeschlagenen Assertions deutlich lesbarere Ausgaben.

Fazit

Mit Data Faker lassen sich einfach verschiedene Fake-Daten erstellen. Die Library deckt hier alle regelmäßig benötigten Bereiche ab. Besonders hilfreich ist die Library aus meiner Sicht für folgende Aspekte:

  1. Automatisiertes Befüllen einer Testdatenbank mit Fake-Daten
  2. Verwendung in Unit-Tests…
    1. …um bei fehlgeschlagenen Assertions lesbarere Ausgaben zu erhalten.
    2. …um z.B. Validierungen zu prüfen.
    3. …um Corner-Cases abzudecken. Besonders mit Blick auf Sonderzeichen und Umlaute hilft die Nutzung von sich ändernden Daten, um bisher unentdeckte Fehler zu bemerken.
  3. Daten für das Ergebnis einer Mock-Schnittstelle

Quellen:

https://github.com/datafaker-net/datafaker/

https://www.datafaker.net/

Zurück zur Übersicht

Kommentar verfassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

*Pflichtfelder

*