Eine testbare Flutter-Architektur mit Riverpod
setState vermischt Logik und UI in derselben Klasse; InheritedWidget propagiert die Daten gut, sagt aber nichts über ihre Erstellung oder ihren Austausch im Test. Riverpod beantwortet beides: ein Dependency-Injection-Container, der reaktive Werte erzeugt, unabhängig vom Widget-Baum.
Providers und Notifiers
Provider stellt einen Wert bereit; ein Notifier stellt einen veränderlichen Wert zusammen mit der Logik bereit, die ihn weiterentwickelt. Mit Code-Generierung ( riverpod_generator ) annotiert man eine Klasse, und build() liefert den Anfangszustand:
ref.watch innerhalb eines Providers erzeugt eine Abhängigkeit : Ändert sich apiClientProvider , wird currentUser automatisch neu berechnet. Dieser Abhängigkeitsgraph ersetzt manuelle setState -Kaskaden.
UI von Logik trennen
WidgetTester :
ref.watch(currentUserProvider) einen AsyncValue , dessen .when(data:, loading:, error:) alle drei Zustände abdeckt — ohne herumgereichten `isLoading`-Boolean .
Dependency Injection und Overrides im Test
InheritedWidget : Jeder Provider ist beim Erstellen des ProviderContainer austauschbar . Im Test injiziert man einen gefälschten API-Client, ohne den Produktionscode anzufassen:
addTearDown stellt sicher, dass er freigegeben wird. Die Riverpod-Testdokumentation beschreibt die pump - und Listener-Patterns im Detail.
Warum nicht setState oder InheritedWidget
setState baut den gesamten State neu auf und koppelt die Logik fest an die UI — ohne Widget-Rendering kein Test möglich. InheritedWidget teilt einen Wert, erfordert aber manuelles Schreiben von updateShouldNotify , unterstützt weder Asynchronität noch Austausch und verliert sich sobald man den BuildContext berührt. Riverpod verschiebt den Zustand aus dem Baum heraus , macht ihn lazy, memoisiert und automatisch freigegeben ( autoDispose ), und macht den Override zum normalen Testweg.
Eine gute Flutter-Architektur misst sich nicht an der Anzahl der Provider, sondern daran: Kann man die Logik testen, ohne jemals ein Widget zu mounten ? Mit Riverpod lautet die Antwort per Konstruktion: ja.