I am trying to create widget splash screen that shows when the app loads and the native splash screen is shown. I created the splash screen and everything seems fine so i decide to create widget test for the splash screen background image and single text on the screen. The test part for the text passes but i have issues with the image.
Widget test error text:
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure was thrown running a test:
Expected: exactly one matching node in the widget tree
Actual: _WidgetTypeFinder:<zero widgets with type "Image" (ignoring offstage widgets)>
Which: means none were found but one was expected
The full splash screen code:
class SplashScreenPage extends StatefulWidget {
const SplashScreenPage({Key? key}) : super(key: key);
@override
State<SplashScreenPage> createState() => _SplashScreenPageState();
}
class _SplashScreenPageState extends State<SplashScreenPage> {
Timer? _timer;
@override
void initState() {
_timer = Timer(const Duration(seconds: 4), () {
Navigator.of(context).pushReplacementNamed(RoutingConst.defaultRoute);
});
super.initState();
}
@override
void dispose() {
_timer!.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/background.png"),
fit: BoxFit.cover,
),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
children: [
const Spacer(),
const Spacer(),
const Spacer(),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Flexible(
child: Text(
"SPLASH SCREEN TEXT",
maxLines: 2,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
style: GoogleFonts.inter(
color: Colors.white,
fontSize: 40,
fontWeight: FontWeight.bold,
),
),
),
],
),
const Spacer(),
],
),
),
]
),
);
}
}
The widget test:
void main() {
//
// Setup
//
Widget createWidgetUnderTest() {
return const MaterialApp(
home: SplashScreenPage(),
);
}
//
// Testing
//
testWidgets(
"Check if splash screen text shows up",
(WidgetTester tester) async {
await tester.pumpWidget(createWidgetUnderTest());
expect(find.text("SPLASH SCREEN TEXT"), findsOneWidget);
},
);
testWidgets(
"Check if splash screen background shows up",
(WidgetTester tester) async {
await tester.pumpWidget(createWidgetUnderTest());
expect(find.byType(Image), findsOneWidget);
},
);
}
The test for the text passes, but the one for the image fails and i can't figure out why. I tried the find.image(AssetImage("asset-path")) but that didn't work aswell. Tried to put key on the container holding the box decoration in and then try to find the container in the test and it finds it so maybie i am doing something wrong in finding image inside box decoration but i don't know how to find it if that's the case.
The Problem:
The
SplashScreenPage
does not contain an actual Image widget, so the finders below used in the test will fail to find anImage
widget.find.byType(Image)
finds aWidget
of typeImage
.find.image()
finds aWidget
of typeImage
orFadeInImage
.Setting an image to a
Container
'sdecoration
does not create anImage
widget, so the finders are inappropriate for this test.The Solution:
Use find.byWidgetPredicate to find the actual
Widget
containing the image, in this case:Container
and add checks to specify the properties of theContainer
you're looking for.Here's the code: