0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Flutter/WidgetTestでUnsupported operation: Cannot set value in unmodifiable Mapエラーが出る

Posted at

環境

訳あって最新版を使っていません(macをCatalinaにアップデートできない==Xcodeの最新版を入れられないので)。
従って、バージョン違いによる不動作などあるかも知れません。お気づきの点があったら是非コメント下さい。

$ flutter --version
Flutter 1.12.13+hotfix.5 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 27321ebbad (4 months ago) • 2019-12-10 18:15:01 -0800
Engine • revision 2994f7e1e6
Tools • Dart 2.7.0

現象

WidgetTestで、pumpWidget(MyApp())しているテストを、他のテストと連続実行したときのみ、以下のエラーが出る。
単独実行したときは、出ない。

══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following UnsupportedError was thrown building MediaQuery(MediaQueryData(size: Size(800.0,
600.0), devicePixelRatio: 3.0, textScaleFactor: 1.0, platformBrightness: Brightness.light, padding:
EdgeInsets.zero, viewPadding: EdgeInsets.zero, viewInsets: EdgeInsets.zero, physicalDepth:
1.7976931348623157e+308, alwaysUse24HourFormat: false, accessibleNavigation: false, highContrast:
false,disableAnimations: false, invertColors: false, boldText: false)):
Unsupported operation: Cannot set value in unmodifiable Map

原因

どうやら、ローカライゼーション用の設定が悪さをしているようです。
Flutterをそのまま実行すると、日本語フォントがおかしくありませんか?それを解消するため、MaterialAppに次のように指定していました。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
   return MaterialApp(
      // 日本語フォント設定
      localizationsDelegates: [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: [
        Locale('ja', ''), // Japanese
      ],
     ....

これの設定を無くすと、大丈夫でした。

このテストの前に実行するテストでは、

return MaterialApp(
      home: HomePage(),
    );

としてダミーのMaterialAppを起動していて、どうやらそのクラスはテストの間で再作成していないらしく、MyAppの設定でImuutableなMapを上書きしようとして怒られているようです。
groupを変えてみても同じでした。

解決策

1.MyAppを起動するテストを先に持ってくる

未設定のプロパティは、特に値が上書きされることはないようなので、

MyApp→ダミーMaterialApp

の順の起動になれば、エラーが起きなくなります。
なので、テストの順番をそのように変えます。
JUnitと違い、Dartのテストは書いた順番に実行されますから、メソッドをカット&ペースとして動かすだけです。

2.TestAppクラスを作ってローカライゼーション設定を入れる

ダミーのMaterialAppを作っていたのを、TestAppクラスとして次のようにします。

class TestApp extends StatelessWidget {
  TestApp(this.widget);

  final Widget widget;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // 日本語フォント設定
      localizationsDelegates: [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: [
        Locale('ja', ''), // Japanese
      ],
      home: widget,
    );
  }
}

///テストコード
await tester.pumpWidget(TestApp(HomePage()));

でも、テスト時にフォントは関係ないしなあ・・・
ということで、悩ましいですが、いったん1の対応を取っています。

なお、テストファイルが違う場合は、作り直されるみたいです。というかファイル毎に別スレッドでテストしているようなログの出方をしていますので、当然ながらファイルが違うテストは全部別インスタンスでしょうね。

というかFlutterのテストレポート見づらい・・・

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?