我试图创建小部件闪屏,显示何时应用程序加载和本机闪屏显示.我创建了闪屏,一切似乎都很好,所以我决定为闪屏背景图像和屏幕上的单个文本创建小部件测试.文本的测试部分通过了,但我对图像有问题.

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);
    },
  );
}

文本的测试通过了,但图像的测试失败了,我不知道为什么.我try 了find.Image(AssetImage("ASSET-PATH")),但效果不佳.试着把 keys 放在装有盒子装饰的容器上,然后在测试中试图找到容器,它发现它可能是我在寻找盒子装饰内部的图像时做了一些错误的事情,但我不知道如何找到它,如果是这样的话.

推荐答案

The Problem:

SplashScreenPage不包含实际的Image widget,因此测试中使用的下面的查找器将无法找到Image小部件.

  • find.byType(Image)会找到类型为ImageWidget.
  • find.image()查找类型为ImageFadeInImageWidget.

将图像设置为Container‘S decoration不会创建Image小部件,因此取景器不适合进行此测试.

The Solution:

使用find.byWidgetPredicate查找包含图像的实际Widget,在本例中为:Container,然后添加判断以指定您要查找的Container的属性.

代码如下:

 testWidgets(
    "Check if splash screen background shows up",
    (WidgetTester tester) async {
      await tester.pumpWidget(createWidgetUnderTest());

      final assetImageFinder = find.byWidgetPredicate(
        (Widget widget) {
          if (widget is Container) {
            final decoration = widget.decoration;

            if (decoration is BoxDecoration) {
              final image = decoration.image;

              if (image is DecorationImage) {
                final imageProvider = image.image;

                if (imageProvider is AssetImage) {
                  return imageProvider.assetName ==
                      "assets/images/background.png";
                }
              }
            }
          }

          return false;
        },
      );

      expect(assetImageFinder, findsOneWidget);
    },
  );

Flutter相关问答推荐

我有一个问题:类型';()=>;Null';不是类型转换中类型';(Int)=>;void';的子类型

Flutter :在后台实现振动

不要跨同步间隔使用BuildContext

Flutter为什么不;没有ListView.iterable()构造函数?

Flutter-Riverpod:如何只从提供者读取一次值

Flutter Xcode 15 错误(Xcode):DT_TOOLCHAIN_DIR 无法用于判断 LIBRARY_SEARCH_PATHS

如何在 Flutter 中设计像 zomato 应用程序一样的搜索字段?

NotifierProvider 每次更新都会重新构建并且值不更新

使用 Flutter 和 Dio 将图像上传到 API

以编程方式在 flutter 中安装 apk 时解析错误

如何使用Riverpod提供程序正确构建搜索栏?

#Flutter/Riverpod - 使用 AsyncNotifier 时是否可以仅调用错误?

Flutter:如何从运行时创建的列表中访问单个子部件的值

Flutter/Dart - 从外部类更新状态

如何根据字符串值动态构建和显示小部件?

如何在 Flutter 中使用简写 IF 禁用单选按钮?

在 Flutter 中,如何使用文本字段和方形图像进行行布局

在 Flutter 中单击时切换按钮 colored颜色 没有改变

在 Flutter Bloc 中具有称为 status 的属性的一种状态或不同的状态,哪个更可取?

未处理的异常:FileSystemException:无法打开文件,路径 = 'assets/res.zip'(操作系统错误:没有这样的文件或目录,errno = 2)