自定义小部件的 Flutter 小部件测试失败

Posted

技术标签:

【中文标题】自定义小部件的 Flutter 小部件测试失败【英文标题】:Flutter widget test of a custom widget fails 【发布时间】:2019-05-23 01:30:53 【问题描述】:

我正在尝试测试自定义小部件GoogleSignInButton

这里是小部件的实现:

import 'package:flutter/material.dart';

class GoogleSignInButton extends StatelessWidget 
  GoogleSignInButton(this.onPressed);

  final Function onPressed;

  @override
  Widget build(BuildContext context) 
    Image _buildLogo() 
      return Image.asset(
        "assets/g-logo.png",
        height: 18.0,
        width: 18.0,
      );
    

    Opacity _buildText() 
      return Opacity(
        opacity: 0.54,
        child: Text(
          "Sign in with Google",
          style: TextStyle(
            fontFamily: 'Roboto-Medium',
            color: Colors.black,
          ),
        ),
      );
    

    return MaterialButton(
      height: 40.0,
      onPressed: this.onPressed,
      color: Colors.white,
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          _buildLogo(),
          SizedBox(width: 24.0),
          _buildText(),
        ],
      ),
    );
  

我正在尝试通过下面的测试来测试onPressed 函数回调。

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import '../lib/ui/widgets/google_sign_in_button.dart';

void main() 
  testWidgets('my first widget test', (WidgetTester tester) async 
    var pressed = false;
    var widget = GoogleSignInButton(
      onPressed: () => () 
            pressed = true;
          ,
    );

    await tester.pumpWidget(
      StatefulBuilder(
        builder: (BuildContext context, StateSetter setState) 
          return MaterialApp(
            home: Material(
              child: Center(
                child: widget,
              ),
            ),
          );
        ,
      ),
    );

    await tester.press(find.byWidget(widget));
    expect(pressed, equals(true));
  );

很遗憾,测试失败了。

我正在通过 flutter test test/widget_test.dart 在命令行上执行我的小部件测试,这是测试的结果:

══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure object was thrown running a test:
  Expected: <true>
  Actual: <false>

When the exception was thrown, this was the stack:
#4      main.<anonymous closure> (file:///home/hans/Development/flutter/recipes_app/test/widget_test.dart:30:5)
<asynchronous suspension>
#5      testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:72:23)
#6      TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:566:19)
<asynchronous suspension>
#9      TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:550:14)
#10     AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:893:24)
#16     AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:890:15)
#17     testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:71:22)
#18     Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:168:27)
<asynchronous suspension>
#19     Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:249:15)
<asynchronous suspension>
#24     Invoker.waitForOutstandingCallbacks (package:test_api/src/backend/invoker.dart:246:5)
#25     Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:166:33)
#30     Declarer.test.<anonymous closure> (package:test_api/src/backend/declarer.dart:165:13)
<asynchronous suspension>
#31     Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:399:25)
<asynchronous suspension>
#45     _Timer._runTimers (dart:isolate/runtime/libtimer_impl.dart:382:19)
#46     _Timer._handleMessage (dart:isolate/runtime/libtimer_impl.dart:416:5)
#47     _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:171:12)
(elided 28 frames from class _FakeAsync, package dart:async, and package stack_trace)

This was caught by the test expectation on the following line:
  file:///home/hans/Development/flutter/recipes_app/test/widget_test.dart line 30

The test description was:
my first widget test
════════════════════════════════════════════════════════════════════════════════════════════════════
00:01 +0 -1: my first widget test [E]                                                                                                                                                                             
  Test failed. See exception logs above.
  The test description was: my first widget test

00:02 +0 -1: Some tests failed.

任何想法为什么测试失败?

【问题讨论】:

【参考方案1】:

你的关闭是错误的:

() => () 
    pressed = true;
  ,

你需要这样写

() 
    pressed = true;
,

或者这样

() => ( pressed = true )

你需要触发tester.tap方法。

这是我的工作代码:

var pressed = false;
var widget = GoogleSignInButton(
  onPressed: () 
        pressed = true;
        debugPrint("Pressed!");
      ,
);

await tester.pumpWidget(
  StatefulBuilder(
    builder: (BuildContext context, StateSetter setState) 
      return MaterialApp(
        home: Material(
          child: Center(
            child: widget,
          ),
        ),
      );
    ,
  ),
);

expect(find.byWidget(widget), findsOneWidget);
await tester.tap(find.byWidget(widget));
expect(pressed, isTrue);

我假设当您运行项目时,您的 Widget 渲染良好并且不会抛出任何错误。

提示:在您的 test_file.dart 更改发生任何更改后创建一个 flutter clean

【讨论】:

以上是关于自定义小部件的 Flutter 小部件测试失败的主要内容,如果未能解决你的问题,请参考以下文章

使用 QtDesigner PyQt4 创建自定义小部件

Flutter 小部件包裹在自定义小部件中

在 Flutter 测试中查找 CustomScrollView 内的小部件

在 Flutter 中编写自定义小部件(第1部分)ー EllipsizedText

Flutter 小部件测试点击 - 不会在指定的小部件上进行测试

如何在 Flutter 小部件中测试回调函数