首页 > 解决方案 > 如何断言占位符文本在 Flutter 小部件测试中消失?

问题描述

假设我想断言,当我在搜索栏小部件中输入文本时,占位符文本会消失。这实际上只是在测试 Flutter 框架,但这是我尝试的第一个小部件测试,只是为了了解如何进行小部件测试,而且它不仅仅是工作。

测试以下 SearchBar 小部件:

import 'package:flutter/material.dart';

const BorderRadius _kBorderRadius = BorderRadius.all(Radius.circular(32.0));
const Color _kBorderColor = Color(0xFF33BFCC);

class SearchBar extends StatelessWidget {
  SearchBar({this.onClose, this.onChanged});

  final Function onClose;
  final Function onChanged;

  @override
  Widget build(BuildContext context) {
    return TextField(
      onChanged: onChanged,
      decoration: InputDecoration(
        suffixIcon: IconButton(
          icon: Icon(Icons.close),
          onPressed: onClose,
        ),
        fillColor: Colors.white,
        filled: true,
        hintText: 'Search',
        contentPadding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
        border: OutlineInputBorder(
          borderRadius: _kBorderRadius,
        ),
        enabledBorder: OutlineInputBorder(
          borderSide: BorderSide(color: _kBorderColor, width: 1.0),
          borderRadius: _kBorderRadius,
        ),
        focusedBorder: OutlineInputBorder(
          borderSide: BorderSide(color: _kBorderColor, width: 2.0),
          borderRadius: _kBorderRadius,
        ),
      ),
    );
  }
}

以及该小部件的以下测试:

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:my_app/ui_components/search_bar.dart';

void main() {
  testWidgets('entering text removes placeholder text',
      (WidgetTester tester) async {
    await tester.pumpWidget(MaterialApp(home: Scaffold(body: SearchBar())));

    await tester.enterText(find.byType(TextField), 'hi');
    await tester.pumpAndSettle();

    final placeholderFinder = find.text('Search');
    final textFinder = find.text('hi');

    expect(textFinder, findsOneWidget);
    expect(placeholderFinder, findsNothing);
  });
}

此测试失败,因为仍然找到“搜索”文本。看看Flutter 如何测试他们自己的文本字段,他们似乎在使用不透明技巧。如果我通过替换尝试相同的技巧

expect(placeholderFinder, findsNothing);

expect(getOpacity(tester, placeholderFinder), 0.0);

其中getOpacity定义为:

double getOpacity(WidgetTester tester, Finder finder) {
  return tester
      .widget<FadeTransition>(
        find.ancestor(
          of: finder,
          matching: find.byType(FadeTransition),
        ),
      )
      .opacity
      .value;
}

我收到以下错误:

运行测试时抛出了以下 StateError: 状态错误:元素太多 抛出异常时,这是堆栈:0 Iterable.single (dart:core/iterable.dart:554:24) 1 WidgetController.widget (package: flutter_test/src/controller.dart:65:30)

有一个更好的方法吗?

标签: flutterflutter-test

解决方案


您可以通过获取小部件firstWidget并进行测试。

testWidgets('Test name', (WidgetTester tester) async {
  // preparing widget...

  final finder = find.byType(FadeTransition)
  expect(finder, findsOneWidget);

  //getting Text object
  Text widget = tester.firstWidget(finder);

  // validating properies
  expect(widget.opacity.value, equals(0));
}

推荐阅读