Help us understand the problem. What is going on with this article?

HTTP通信するWidgetをテストする(Flutter)

More than 1 year has passed since last update.

ここ最近、Flutterを使ったクロスプラットフォームのアプリを作ろうドキュメントを片手にと勉強しています。その中でハマった、HTTP通信が含まれるWidgetのテスト方法について書き残します。最終的には以下のコードでテストが成功します。

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:http/testing.dart';
import 'package:http/http.dart';

class Test extends StatelessWidget {
  Client client = Client();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: FutureBuilder(
        future: getWord(),
        builder: (BuildContext context, AsyncSnapshot snapshot) {
          if (!snapshot.hasData) return CircularProgressIndicator();
          return Text(snapshot.data);
        }
      ),
    );
  }

  Future<String> getWord() async {
    final response = await client.get('http://example.com');
    return response.body;
  }
}

void main() {
  testWidgets('http mock', (WidgetTester tester) async {
    final mockClient = MockClient((_) async => Response('Hello World', 200));
    final test = Test();
    test.client = mockClient;

    await tester.pumpWidget(test);
    await tester.pumpAndSettle();
    expect(find.text('Hello World'), findsOneWidget);
  });
}

やっていることはHTTPクライアントをモックに差し替えてからテストする、これだけです。因みにパッケージは次の通りです。

pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  http: ^0.12.0+2

dev_dependencies:
  flutter_test:
    sdk: flutter
  mockito: ^4.1.0

それでは、順を追って説明していきます。

Widgetの作成

まずはテスト対象のWidgetを作成します。APIからのレスポンスを表示するだけのWidgetです。レスポンスを待ってからWidgetをビルドしたかったため、FutureBuilderを使用しています。このclientの中身をモッククライアントに差し替えることが今回の肝です。

class Test extends StatelessWidget {
  Client client = Client();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: FutureBuilder(
        future: getWord(),
        builder: (BuildContext context, AsyncSnapshot snapshot) {
          if (!snapshot.hasData) return CircularProgressIndicator();
          return Text(snapshot.data);
        }
      ),
    );
  }

  Future<String> getWord() async {
    final response = await client.get('http://example.com');
    return response.body;
  }
}

モッククライアントの作成

Clientを差し替えるためのモックを作成します。httpパッケージに用意されているモック作成用のMockClientクラスを利用します。ここでは、MockClientのレスポンスが'Hello World'と200ステータスを返すように設定しています。今回は、単純にレスポンスの表示するだけですが、テストの内容によってはJSONを返すようにしたり、目的に合わせてレスポンスを設定することができます。

final mockClient = MockClient((_) async => Response('Hello World', 200));

テストの実行

ここまでで、Widgetとモッククライアントができました。あとはテストを実行するだけです。Testウィジェトのインスタンスを生成して、インスタンスのclientの中身をmockClientに差し替えます。最後にtester.pumpWidgetでWidgetをビルドし、tester.pumpAndSettleでFutureBuilderが生成する「Hello World」が表示されるのを待つことでテストが成功します。

testWidgets('print test', (WidgetTester tester) async {
  final mockClient = MockClient((_) async => Response('Hello World', 200));
  final test = Test();
  test.client = mockClient;

  await tester.pumpWidget(test);
  await tester.pumpAndSettle();
  expect(find.text('Hello World'), findsOneWidget);
});

以上が、HTTP通信するWidgetのテスト方法についての記事でした。お役に立てたら幸いです!

darumock
フロントエンドをメインに書いています。最近はRubyも勉強しています。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away