Flutterでmockitoのanalyzer互換エラーをローカルパッチで回避する方法
mockitoの5.4.5とanalyzer7.xで競合エラー発生
Flutterプロジェクトで mockito 5.4.5
を使用している際、Dart SDK 3.x + analyzer 7.x
環境下で以下のようなビルドエラーに遭遇することがあります。今回の僕のケースだと、auto_route_generator 9.0.0
が依存関係でmockito 5.4.5
を読み込むので、それに巻き込まれてビルドエラーが起きてました。
Building package executable... (6.0s)
Built build_runner:build_runner.
[INFO] Generating build script completed, took 655ms
[WARNING] ../../.pub-cache/hosted/pub.dev/mockito-5.4.5/lib/src/builder.dart:845:23: Error: The argument type 'InterfaceElement' can't be assigned to the parameter type 'InterfaceElementImpl'.
- 'InterfaceElement' is from 'package:analyzer/dart/element/element.dart' ('../../.pub-cache/hosted/pub.dev/analyzer-7.4.1/lib/dart/element/element.dart').
- 'InterfaceElementImpl' is from 'package:analyzer/src/dart/element/element.dart' ('../../.pub-cache/hosted/pub.dev/analyzer-7.4.1/lib/src/dart/element/element.dart').
.getInterface(interfaceElement)
^
../../.pub-cache/hosted/pub.dev/mockito-5.4.5/lib/src/builder.dart:1173:26: Error: Can't assign spread elements of type 'TypeParameterElement' to collection elements of type 'TypeParameterElementImpl'.
- 'TypeParameterElement' is from 'package:analyzer/dart/element/element.dart' ('../../.pub-cache/hosted/pub.dev/analyzer-7.4.1/lib/dart/element/element.dart').
- 'TypeParameterElementImpl' is from 'package:analyzer/src/dart/element/element.dart' ('../../.pub-cache/hosted/pub.dev/analyzer-7.4.1/lib/src/dart/element/element.dart').
...classToMock.typeParameters,
^
../../.pub-cache/hosted/pub.dev/mockito-5.4.5/lib/src/builder.dart:1174:15: Error: Can't assign spread elements of type 'TypeParameterElement' to collection elements of type 'TypeParameterElementImpl'.
- 'TypeParameterElement' is from 'package:analyzer/dart/element/element.dart' ('../../.pub-cache/hosted/pub.dev/analyzer-7.4.1/lib/dart/element/element.dart').
- 'TypeParameterElementImpl' is from 'package:analyzer/src/dart/element/element.dart' ('../../.pub-cache/hosted/pub.dev/analyzer-7.4.1/lib/src/dart/element/element.dart').
...?aliasedElement?.typeParameters,
^
../../.pub-cache/hosted/pub.dev/mockito-5.4.5/lib/src/builder.dart:1180:27: Error: The argument type 'InterfaceElement' can't be assigned to the parameter type 'InterfaceElementImpl'.
- 'InterfaceElement' is from 'package:analyzer/dart/element/element.dart' ('../../.pub-cache/hosted/pub.dev/analyzer-7.4.1/lib/dart/element/element.dart').
- 'InterfaceElementImpl' is from 'package:analyzer/src/dart/element/element.dart' ('../../.pub-cache/hosted/pub.dev/analyzer-7.4.1/lib/src/dart/element/element.dart').
.getInterface(classToMock)
^
../../.pub-cache/hosted/pub.dev/mockito-5.4.5/lib/src/builder.dart:1792:65: Error: The argument type 'InterfaceElement' can't be assigned to the parameter type 'InterfaceElementImpl'.
- 'InterfaceElement' is from 'package:analyzer/dart/element/element.dart' ('../../.pub-cache/hosted/pub.dev/analyzer-7.4.1/lib/dart/element/element.dart').
- 'InterfaceElementImpl' is from 'package:analyzer/src/dart/element/element.dart' ('../../.pub-cache/hosted/pub.dev/analyzer-7.4.1/lib/src/dart/element/element.dart').
final overriddenMethods = inheritanceManager.getOverridden2(class_, name);
^
../../.pub-cache/hosted/pub.dev/mockito-5.4.5/lib/src/builder.dart:1800:46: Error: The argument type 'InterfaceElement' can't be assigned to the parameter type 'InterfaceElementImpl'.
- 'InterfaceElement' is from 'package:analyzer/dart/element/element.dart' ('../../.pub-cache/hosted/pub.dev/analyzer-7.4.1/lib/dart/element/element.dart').
- 'InterfaceElementImpl' is from 'package:analyzer/src/dart/element/element.dart' ('../../.pub-cache/hosted/pub.dev/analyzer-7.4.1/lib/src/dart/element/element.dart').
overriddenMethod.enclosingElement3 as InterfaceElement, name);
^
[INFO] Precompiling build script... completed, took 5.6s
[SEVERE] Failed to precompile build script .dart_tool/build/entrypoint/build.dart.
This is likely caused by a misconfigured builder definition.
Failed to update packages.
これは mockito
が analyzer
の内部実装に依存しているために発生する互換性の問題です。analyzerのダウングレードをしたらいいのかもしれないけど、修正地獄に陥るので、mockitoにローカルパッチを当てて修正するのが問題解決として妥当です。
✋ 解決策:mockito にローカルパッチを当てて使用する
mockito
をプロジェクト内にコピーする
1. mkdir -p patched_packages/mockito
cp -r ~/.pub-cache/hosted/pub.dev/mockito-5.4.5/* patched_packages/mockito/
※Windowsの場合は %APPDATA%\Pub\Cache\hosted\pub.dev\mockito-5.4.5\*
を利用してください。
builder.dart
を修正
2. パス: patched_packages/mockito/lib/src/builder.dart
InterfaceElement
を InterfaceElementImpl
にキャストするよう修正します。
修正前: 845行目
.getInterface(interfaceElement)
修正後:
.getInterface(interfaceElement as InterfaceElementImpl)
修正前:1790行目
final overriddenMethods = inheritanceManager.getOverridden2(class_, name);
修正後:
final overriddenMethods = inheritanceManager.getOverridden2(class_ as InterfaceElementImpl, name);
修正前:1798行目
overriddenMethod.enclosingElement3 as InterfaceElement, name);
修正後:
overriddenMethod.enclosingElement3 as InterfaceElementImpl, name);
なお、exampleとtestディレクトリはエラーが出るので削除。必要に応じて、ヘッダーの外部読み込み宣言で下記も追加
import 'package:analyzer/src/dart/element/element.dart';
pubspec.yaml
にローカルパス指定を追加
3. dependency_overrides:
mockito:
path: patched_packages/mockito
4. キャッシュとロックファイルをクリアして再取得
rm pubspec.lock
flutter clean
flutter pub get
✅ 結果
この手順で mockito 5.4.5
を手元で修正し、CIやローカルでもビルドエラーなく使用できるようになります。CIで使うんであれば、patched_packages/mockitoをコミットしとく必要があります。
🔚 補足:なぜ起こるのか?
mockito
は analyzer
の private API(InterfaceElementImpl
) に依存しています。
Dart 3.x以降の analyzer 7.x
では構造が変更され、互換性が失われたことで型の不一致エラーが発生しています。
このバグは公式Issueでも報告されています:
📝 まとめ
対応方法 | 安定性 | コメント |
---|---|---|
mockitoをローカルパッチする | ◎ | 最も確実。CIでも安定動作 |
mockitoのバージョンを下げる | △ | 他依存パッケージとの衝突に注意 |
修正版リリースを待つ | × | 不確実、時間がかかる可能性あり |
困っている方の助けになれば幸いです 🙌
Discussion