JUnit MethodSource und Nested
In diesem Artikel zeigen wir, wie parametrisierte Tests in JUnit zusammen mit @Nested
funktionieren, und was hier die eleganteste Variante ist.
In vielen Projekten kommen Utility-Klassen zum Einsatz. Nehmen wir an, wir haben eine StringUtil
-Klasse, welche eine Methode extractLastTrimmed
enthält. In der Realität würden sich natürlich hier noch viele weitere Hilfsmethoden finden.
Wenn man Tests für eine solche Klasse schreibt, ergeben sich schnell eine große Anzahl von Testmethoden. Eine Möglichkeit, Tests zu organisieren, bietet die Verwendung von @Nested. Dies ermöglicht es, Tests z.B. nach Methoden zu gruppieren, was die Lesbarkeit und Wartbarkeit verbessert.
Allerdings gibt es eine Einschränkung, insbesondere wenn parametrisierte Tests verwendet werden, die eine Methode als Quelle für ihre Parameter verwenden (@MethodSource). Die Methode, welche die Parameter bereitstellt, wird leider nur gefunden, wenn der vollqualifizierte Name der Klasse plus Methodenname als String angegeben wird.
Dies ist nicht nur unschön, sondern auch fehleranfällig bezüglich Umbenennungen von Package, Klasse oder Methode:
Eine elegantere Alternative bietet hier die Verwendung von @ArgumentsSource anstelle von @MethodSource
. Dies wird deutlich in der überarbeiteten Version unseres Tests:
Statt einer einfachen statischen Methode hat man nun eine kleine Klasse, die das Interface ArgumentsProvider implementiert und die provideArguments
-Methode bereitstellt.
Anstelle von @MethodSource
verwendet man nun @ArgumentsSource
und gibt dort den Namen der Klasse an.
Der minimale zusätzliche Aufwand gegenüber der Variante mit @MethodSource
zahlt sich aus, da die Verwendung von @ArgumentsSource
auch mit @Nested
funktioniert und Refactoring-sicher ist.
Meiner Meinung nach sollte man @MethodSource
ohne Methodenname grundsätzlich eher vermeiden, da diese Magie, mit der das Test-Framework die zugehörige Methode sucht, möglicherweise nicht jedem Entwickler bekannt ist und daher die Lesbarkeit der Tests erschwert.
Das vollständige Beispiel findet sich auf github.