Flutter - 如何 select Widget 测试中的 DropdownButton 项目

Flutter - How to select DropdownButton item in widget test

我试过这样选择 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(),
    );
  }
}

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

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

}

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

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