Hallo zusammen!
Ich bin gerade dabei, für mein Spiel Unit-Tests zu schreiben. Dabei bin ich auf ein Problem mit statischen Methoden/Variablen in der folgenden Konstruktion gestoßen:
Grober Ablauf: Die Klasse
ProfessionTypes enthält alle im Spiel verfügbaren Berufstypen. Dazu enthält die Klasse die Pfade von JSON-Dateien, in denen die Berufe definiert sind. Nachdem die Dateien von einem externen Loading-Screen geladen werden, wird die statische
ProfessionTypes#initialize(AssetManager)-Methode aufgerufen und die
ProfessionType-Objekte werden geladen und gesetzt.
Anschließend ist beispielsweise in der statischen Variable
ProfessionTypes.SMITH der Berufstyp des Schmiedes enthalten.
|
Quellcode
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
// Enthält alle einzelnen ProfessionTypes als statische Variablen
public class ProfessionTypes {
// Der Berufstyp des Schmiedes
public static ProfessionType SMITH;
// Der Pfad zur Datei, die Informationen über den Schmied enthält
@Asset(JSON.class)
public static final String SMITH_JSON_PATH = "data/professions/smith.json";
private ProfessionTypes() {
// shouldn't get instantiated
}
// Wird vom externen Loading-Screen aufgerufen; setzt die statischen Variablen
public static void initialize(AssetManager assetManager) {
SMITH = assetManager.get(SMITH_JSON_PATH).getData(ProfessionType.class);
}
// Ein einzelner Berufstyp
public static class ProfessionType {
private String name;
ProfessionType() {
}
public String getName() {
return name;
}
}
}
|
Grund für das Vorgehen: Grund für die statischen Variablen und damit auch die statische
#initialize(AssetManager)-Methode ist, dass die Variablen (wie beispielsweise
SMITH) quasi ein „dynamisches Enum“ darstellen sollen.
Heißt: Einfach aufrufbar (
ProfessionTypes.SMITH), mit „
==“ vergleichbar, aber trotzdem durch externe Dateien im Inhalt (bspw. Name, etc.) bestimmt.
Problem: Beim Schreiben der Tests ist mir aufgefallen, dass sich statische Methoden mit Mockito leider nicht mocken lassen und
PowerMockito mit JUnit 5 noch nicht funktioniert.
Gerade bei statischen Utility-Methoden (die beispielsweise einen zufälligen Beruf zurückgeben, s.u.) zeigt sich das Problem: Ruft irgendeine der zu testenden Klassen diese Utility-Methode auf, müssen vorher die entsprechenden Types geladen werden. Das ist für abgegrenzte Unit-Tests eher unpraktisch.
|
Quellcode
|
1
2
3
4
5
6
7
|
public class PlayerUtils {
public Player getRandomPlayer() {
return new Player("Vorname", "Nachname", RandomUtils.getRandomElement(ProfessionTypes.ALL_TYPES));
}
}
|
Jetzt stellt sich mir die Frage, wie ich das Problem am besten umgehe. Mir ist klar, dass die Konstruktion mit den statischen Variablen (
ProfessionTypes.SMITH) nicht die eleganteste ist, eine wirklich bessere Lösung fällt mir aber ehrlich gesagt auch nicht ein.
Was denkt ihr dazu: Liegt das Problem eher in den statischen Utility-Methoden? Sollte ich auf JUnit 4 downgraden, um über PowerMockito die Utility-Methoden (
PlayerUtils#getRandomPlayer()) mocken zu können? Oder übersehe ich vielleicht auch einfach nur, wie sich die Types recht simpel mocken ließen?