FlutterのUnit TestでコンポーネントレベルのWidgetを単品でテストする際の注意点

概要

単純に単品WidgetをpumpWidgetした際に発生するエラーが以下

══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞════════════════════════════
The following assertion was thrown building _InkResponseStateWidget(gestures: [tap], mouseCursor:
ButtonStyleButton_MouseCursor, clipped to BoxShape.rectangle, dirty, state:
_InkResponseState#4b944):
No Directionality widget found.
...
Typically, the Directionality widget is introduced by the MaterialApp or WidgetsApp widget at the
top of your application widget tree. It determines the ambient reading direction and is used, for
example, to determine how to lay out text, how to interpret "start" and "end" values, and to resolve
EdgeInsetsDirectional, AlignmentDirectional, and other *Directional objects.

Directionarity Widget (言語によって異なるレイアウト構成を管理するWidget)がないため、UIを構築できないと言っている。

解決策

MaterialAppにDirectionarity Widgetが内包されるため、これで包んであげればよい。例えば、

testWidgets('ボタン名が正しい', (WidgetTester tester) async {
      await tester.pumpWidget(
        MaterialApp(
          home: CButton(child: const Text('button_title')),
        ),
      );
      expect(find.text('button_title'), findsOneWidget);
    });
  });

利用頻度の高いと思われる構成なので、Unit Test用のutilファイルを作って共通化してもよい。

import 'package:flutter/material.dart';

class TestUtil {
  static Widget setApp(Widget widget) {
    return MaterialApp(home: widget);
  }
}

上記だと文字数はそんなに変わらないが、タイトルを付けたりルーティングやテーマ設定を追加したりして単体Widgetテスト時のApp構成を拡張する必要性が出てきた場合に保守性が上がる。

参考(https://qiita.com/chooyan_eng/items/6ffd5b07de07edafd304#materialapp-%E3%81%A7%E5%9B%B2%E3%81%86)