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 にローカルパッチを当てて使用する
1. mockito をプロジェクト内にコピーする
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\* を利用してください。
2. builder.dart を修正
パス: 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';
3. pubspec.yaml にローカルパス指定を追加
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