如何测试Flutter中的url_launcher打开邮件应用程序?

9

我有一个Snackbar和一个SnackbarAction,点击它应该打开默认的电子邮件应用程序,并带有默认的主题和正文。我想知道是否有可能通过一些单元测试来验证这是否真的发生了。

我的Snackbar代码如下:

SnackBar get snackbar =>
      SnackBar(
          content: Text(message),
          action: SnackBarAction(
              key: const Key('ErrorSnackbarAction'),
              label: AppLocalizations
                  .of(_context)
                  .report,
              onPressed: () async => await launch('mailto:test@test.com?subject=TestSubject&body=TestBody')));

我已经在验证外观,它运行良好:

group('ErrorSnackbar', () {
  testWidgets('appearance test', (WidgetTester tester) async {
    await tester.pumpWidget(_generateSnackbarApp());

    await _showSnackbar(tester);

    expect(find.text(userMessage), findsOneWidget);
    expect(find.byWidgetPredicate((Widget widget) =>
    widget is SnackBarAction && widget.label == 'Report'), findsOneWidget);
  });

  testWidgets('error report test', (WidgetTester tester) async {
    await tester.pumpWidget(_generateSnackbarApp());

    await _showSnackbar(tester);

    tester.tap(find.byKey(errorSnackbarAction));
    await tester.pump();

   // how to verify that the default email app was opened
  // with expected subject and body?

  });
});
3个回答

9

简短回答:您无法做到。

mailto 启动是由设备的操作系统处理的,超出了 flutter 应用程序的上下文。由于 Flutter 测试包专注于 Flutter 应用程序,因此操作系统上发生的情况无法控制。


2

单元测试方面

我认为最好的测试方法是使用自己的类来包装url launcher。

这样,您可以模拟它,并检查您的逻辑是否调用了您的包装器类函数来启动邮件应用程序。这应该足够了。

至于实际的邮件应用程序或浏览器(在我的情况下),您应该相信库会按照其预期工作,因此不需要进行单元测试。


1
您可以确保调用了launchUrl并传递了预期的参数。应该对url_launcher包进行测试。因此,当我们使用mailto:模式调用launchUrl时,我们可以期望邮件应用程序打开。
以下是如何测试url_launcher包的简短介绍:
plugin_platform_interfaceurl_launcher_platform_interface添加到您的开发依赖项中:
dev_dependencies:
  flutter_test:
    sdk: flutter
  plugin_platform_interface: any
  url_launcher_platform_interface: any

复制url_launcher包中的mock_url_launcher_platform.dart文件:https://github.com/flutter/plugins/blob/main/packages/url_launcher/url_launcher/test/mocks/mock_url_launcher_platform.dart

现在,您可以像以下示例一样测试launchUrl调用:

void main() {
  late MockUrlLauncher mock;

  setUp(() {
    mock = MockUrlLauncher();
    UrlLauncherPlatform.instance = mock;
  });

  group('$Link', () {
    testWidgets('calls url_launcher for external URLs with blank target',
        (WidgetTester tester) async {
      FollowLink? followLink;

      await tester.pumpWidget(Link(
        uri: Uri.parse('http://example.com/foobar'),
        target: LinkTarget.blank,
        builder: (BuildContext context, FollowLink? followLink2) {
          followLink = followLink2;
          return Container();
        },
      ));

      mock
        ..setLaunchExpectations(
          url: 'http://example.com/foobar',
          useSafariVC: false,
          useWebView: false,
          universalLinksOnly: false,
          enableJavaScript: true,
          enableDomStorage: true,
          headers: <String, String>{},
          webOnlyWindowName: null,
        )
        ..setResponse(true);
      await followLink!();
      expect(mock.canLaunchCalled, isTrue);
      expect(mock.launchCalled, isTrue);
    });
  });
}

我从https://github.com/flutter/plugins/blob/main/packages/url_launcher/url_launcher/test/link_test.dart复制了这个测试。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接