ここ最近、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クライアントをモックに差し替えてからテストする、これだけです。因みにパッケージは次の通りです。
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のテスト方法についての記事でした。お役に立てたら幸いです!