Flutter - 如何在小部件测试中选择 DropdownButton 项

Posted

技术标签:

【中文标题】Flutter - 如何在小部件测试中选择 DropdownButton 项【英文标题】:Flutter - How to select DropdownButton item in widget test 【发布时间】:2021-10-30 21:25:52 【问题描述】:

我尝试像这样选择DropdownButton item

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:dropdown_test_sample/main.dart';

void main() 
  testWidgets('Select Dropdown item test', (WidgetTester tester) async 
    // Build our app and trigger a frame.
    await tester.pumpWidget(const SampleApp());

    final dropdown = find.byKey(const ValueKey('dropdown'));

    await tester.tap(dropdown);
    await tester.pumpAndSettle();

    final dropdownItem = find.byKey(const ValueKey('First item key'));

    await tester.tap(dropdownItem);
    await tester.pumpAndSettle();
  );

但不幸的是,它抛出了这个异常:

似乎有什么东西会不断用相同的键创建相同的DropdownButton item,从而导致小部件测试失败,因为tester.tap() 不能同时“点击”两个小部件。

这是DropdownButton 小部件的完整实现:

import 'package:flutter/material.dart';

void main() 
  runApp(const SampleApp());


class SampleApp extends StatelessWidget 
  const SampleApp(Key? key) : super(key: key);

  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      title: 'Dropdown Test Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const Home(),
    );
  


class Home extends StatelessWidget 
  const Home(Key? key) : super(key: key);

  @override
  Widget build(BuildContext context) 
    return const Scaffold(
      body: Center(
        child: DummyDropdown(
          key: ValueKey('dropdown'),
        ),
      ),
    );
  


class DummyDropdown extends StatefulWidget 
  const DummyDropdown(Key? key) : super(key: key);

  @override
  State<DummyDropdown> createState() => _DummyDropdownState();


class _DummyDropdownState extends State<DummyDropdown> 
  String? text = 'Dropdown';
  String? textValue;

  @override
  Widget build(BuildContext context) 
    return DropdownButton<String>(
      value: textValue,
      underline: Container(),
      dropdownColor: Theme.of(context).cardColor,
      style: Theme.of(context).textTheme.bodyText2,
      hint: Text(
        text!,
      ),
      icon: const Icon(Icons.keyboard_arrow_down),
      onChanged: (newValue) 
        setState(
          () 
            textValue = newValue;
            text = newValue;
          ,
        );
      ,
      items: <String>['First item', 'Second item', 'Third item']
          .map<DropdownMenuItem<String>>(
        (value) 
          return DropdownMenuItem<String>(
            value: value,
            key: ValueKey('$value key'),
            child: Text(
              value,
            ),
          );
        ,
      ).toList(),
    );
  

【问题讨论】:

【参考方案1】:

下拉按钮中的小部件测试与其他小部件不同,请参阅here 了解更多信息。在这种情况下,从文本“First Item”中选择最后一个元素。这将起作用。

    import 'package:flutter/material.dart';
    import 'package:flutter_test/flutter_test.dart';
    
    import 'package:testapp/main.dart';
    
    void main() 
  testWidgets('Select Dropdown item test', (WidgetTester tester) async 
    // Build our app and trigger a frame.
    await tester.pumpWidget(const SampleApp());

    final dropdown = find.byKey(const ValueKey('dropdown'));

    await tester.tap(dropdown);
    await tester.pumpAndSettle();

    ///if you want to tap first item
    final dropdownItem = find.text('First item').last;

    await tester.tap(dropdownItem);
    await tester.pumpAndSettle();
  );


问题就在这里。当我们点击下拉菜单时,一个已经被选中,另一个没有被选中。因此,您可以使用文本值测试该项目。

final dropdownItem = find.text('First item').last;

【讨论】:

以上是关于Flutter - 如何在小部件测试中选择 DropdownButton 项的主要内容,如果未能解决你的问题,请参考以下文章

如何在小部件测试期间存根不属于类的函数?

如何在小部件测试中找到屏幕外的 ListView 子项?

在小部件测试中处理提供程序

如何在 Flutter 小部件测试中执行缩放(捏缩放)多指手势?

Flutter - 动态小部件定位

如何在小部件的容器内显示 pdf [flutter-web]