📑
Swift Unit Testで"Undefined symbol"が流れるときの原因と実践対処ノート
はじめに
SwiftUIプロジェクトでUnit Testを実行した際、以下のようなリンカーエラーが発生しました。
Undefined symbol: type metadata for <AppModule>.<EnumName>
Undefined symbol: <AppModule>.<ViewModelName>.<PropertyName>.getter
Undefined symbol: <AppModule>.<ViewModelName>.<MethodName>() -> ()
...
Linker command failed with exit code 1
原因を深掘りする
1. Test PlanにTest Targetが含まれていない
なぜ起こる?
- 自動生成された.xctestplanファイルはデフォルトで空の状態。明示的にターゲットを追加しない限り、テスト対象が存在しない扱いになる。
何が問題?
- 実行時に「No Tests」と表示され、Unit Test自体が走らない。
対処法
- .xctestplanファイルを開き、「Choose Targets」でUnit/UI Testターゲットを選択して保存する。
2. Defines Moduleが無効になっている
なぜ起こる?
- Swiftのモジュールは、Defines Module = Yesにしないと、外部から型情報を認識できない仕様になっている。
何が問題?
-
@testable import
を使った際、Appターゲットの型情報が見えず、Undefined Symbolエラーが発生する。
対処法
- AppターゲットのBuild Settingsで「Defines Module」をYesに設定する。
3. Host Applicationの設定がされていない
なぜ起こる?
- Unit Testターゲットでは、実行対象のアプリケーション(Host Application)を指定しないと、リンクエラーになる。
何が問題?
- テスト対象のクラスや関数にアクセスできず、ビルド失敗に直結する。
対処法
- TestターゲットのGeneralタブで、正しいAppターゲットをHost Applicationとして設定する。
4. Build Phasesにソースファイルが含まれていない
なぜ起こる?
- 新規追加した.swiftファイルがTarget Membershipには追加されても、Build PhasesのCompile Sourcesに入っていない場合がある。
何が問題?
- リンク対象に含まれないため、実行時にシンボル解決エラーが発生する。
対処法
- AppターゲットのBuild Phases > Compile Sourcesに対象.swiftファイル(例:
<ViewModelName>.swift
)を手動で追加する。
実際に行った対処まとめ
- Test Planにターゲットを追加する
- Defines ModuleをYesに設定する
- Host Applicationを正しく設定する
- Build Phaseに必要なソースファイルを追加する
- クリーンビルド(Shift + Command + K)を実施する
まとめ:Unit Test地雷マップ
- Target Membershipだけで安心しない
- Defines ModuleとHost Applicationの設定を必ず確認する
- Swift Package Manager導入時とのビルド挙動の違いに注意する
特に**@testable import**を多用する環境では、モジュール設定やホストアプリ設定を少しでもミスすると、Undefined Symbolエラーが頻発するので要注意です。
これを読んだ誰かが、同じ地雷を踏まずに済むことを願って。
参考リンク
Discussion