😃

flutter testでurl_launcherのメソッドが呼ばれたことを確認

2021/10/10に公開

はじめに

flutter testでurl_launcherのメソッドが呼ばれたことを確認する方法です。
url_launcherで使用するメソッド(canLaunch, launch)がスタティックメソッドのため、単純にmockitoでmockにすることが出来なかったため、試行錯誤した最終のもとを記載します。

環境

  • flutter: 2.5.2
  • url_launcher: 6.0.11
  • mockito: 5.0.16

コード

// Package imports:
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart';

// Project imports:
import 'sample_test.mocks.dart';

class SampleViewModel {
  Future<void> openUrl(String url) async {
    if (await canLaunch(url)) {
      await launch(url);
    }
  }
}

class FakeUrlLauncherPlatform extends Fake
    with MockPlatformInterfaceMixin
    implements UrlLauncherPlatform {}

([FakeUrlLauncherPlatform])
void main() {
  late MockFakeUrlLauncherPlatform mockUrlLauncherPlatform;

  setUp(() {
    mockUrlLauncherPlatform = MockFakeUrlLauncherPlatform();
    UrlLauncherPlatform.instance = mockUrlLauncherPlatform;
  });

  test('openUrl', () async {
    final viewModel = SampleViewModel();

    const url = 'https://example.com';

    when(mockUrlLauncherPlatform.canLaunch(url)).thenAnswer((_) async => true);
    when(mockUrlLauncherPlatform.launch(url,
        useSafariVC: true,
        useWebView: false,
        enableJavaScript: false,
        enableDomStorage: false,
        universalLinksOnly: false,
        headers: {})).thenAnswer((_) async => true);

    await viewModel.openUrl(url);

    verify(mockUrlLauncherPlatform.canLaunch(url));
    verify(mockUrlLauncherPlatform.launch(url,
        useSafariVC: true,
        useWebView: false,
        enableJavaScript: false,
        enableDomStorage: false,
        universalLinksOnly: false,
        headers: {}));
  });
}

mockito

mockitoのmockやwhen, verifyについては、こちらを参照ください。
https://pub.dev/packages/mockito

UrlLauncherPlatform.instance

url_launcherのメソッド(canLaunch, launch)は、UrlLauncherPlatform.instanceで取得したインスタンスのメソッドを実行しています。
そのため、それをmockに差し替えることでメソッドが呼ばれたことを確認できるようにしています。
https://github.com/flutter/plugins/blob/url_launcher-v6.0.12/packages/url_launcher/url_launcher/lib/url_launcher.dart

FakeUrlLauncherPlatform

UrlLauncherPlatform.instanceに設定するインスタンスですが、UrlLauncherPlatformのままではPlatformInterface.verifyTokenでエラーとなるため使用できませんでした。
そのため、MockPlatformInterfaceMixinを使用したFakeクラスを作成し、そのmockを作成するようにしています。

https://github.com/flutter/plugins/blob/url_launcher_platform_interface-v2.0.4/packages/url_launcher/url_launcher_platform_interface/lib/url_launcher_platform_interface.dart#L37
https://github.com/flutter/plugins/blob/plugin_platform_interface-v2.0.2/packages/plugin_platform_interface/lib/plugin_platform_interface.dart

まとめ

url_launcherのメソッドが呼ばれたことを確認することができました。
当初は、MethodChannelのinvokeMethodで確認する実装をしたのですが、もっと手前で確認する方法はないか調査して、このような方法となりました。
もっと簡単は方法などあれば、教えて下さい。

Discussion