Xcodeでユニットテストを実行しようとするとFabricエラーが発生する件

Xcodeでユニットテストを実行しようとするとFabricエラー（ `FABException` ）が発生する現象について、（暫定的ですが）対応方法が分かったのでメモしておきます。

## 前提

Xcodeバージョン

```
Version 11.4 (11E146)
```

CocoaPodsライブラリバージョン

```
Crashlytics (3.14.0)
Fabric (1.10.2)
Firebase/Core (6.21.0)
```

## エラーの内容

Xcodeでユニットテストを実行しようとしたところ、以下のようなエラーが発生しました。

```
2020-04-14 21:25:16.896671+0900 my-app.debug[11653:9277327] [GoogleDataTransport][I-GDTCOR001006] There was an error reading extension bytes from disk: Error Domain=NSCocoaErrorDomain Code=260 "The file “ event-15836755976515215681”  couldn’ t be opened because there is no such file." UserInfo={NSFilePath=/Users/username/Library/Developer/CoreSimulator/Devices/388F2986-4BFC-4913-ABAC-60C79B78307E/data/Containers/Data/Application/67018EDE-63CF-41B1-AF95-78A9BD40EE86/Library/Caches/google-sdks-events/event-15836755976515215681, NSUnderlyingError=0x600002a1d3b0 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}
2020-04-14 21:25:16.897135+0900 my-app.debug[11653:9277327] [GoogleDataTransport][I-GDTCOR001006] There was an error reading extension bytes from disk: Error Domain=NSCocoaErrorDomain Code=260 "The file “ event-15836102738338756022”  couldn’ t be opened because there is no such file." UserInfo={NSFilePath=/Users/username/Library/Developer/CoreSimulator/Devices/388F2986-4BFC-4913-ABAC-60C79B78307E/data/Containers/Data/Application/67018EDE-63CF-41B1-AF95-78A9BD40EE86/Library/Caches/google-sdks-events/event-15836102738338756022, NSUnderlyingError=0x600002a57330 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}
2020-04-14 21:25:16.978966+0900 my-app.debug[11653:9277054] [Crashlytics] Version 3.14.0 (144)
2020-04-14 21:25:17.047625+0900 my-app.debug[11653:9277054] *** Terminating app due to uncaught exception 'FABException', reason: '[Fabric] Value of Info.plist key "Fabric" must be a NSDictionary.'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff23e3dcce __exceptionPreprocess + 350
    1   libobjc.A.dylib                     0x00007fff50b3b9b2 objc_exception_throw + 48
    2   CoreFoundation                      0x00007fff23e3db0c +[NSException raise:format:] + 188
    3   my-app.debug            0x00000001102b4240 -[Fabric validFabricConfigFromInfoPlist:] + 334
    4   my-app.debug            0x00000001102b3e21 -[Fabric fabricConfig] + 127
    5   my-app.debug            0x00000001102b3f6e -[Fabric APIKey] + 285
    6   my-app.debug            0x000000011027bf43 -[Crashlytics APIKey] + 55
    7   my-app.debug            0x00000001102873ee -[CLSCrashReportingController APIKey] + 57
    8   my-app.debug            0x0000000110286ace -[CLSCrashReportingController startWithProfilingMark:betaToken:] + 258
    9   my-app.debug            0x000000011027b959 __20-[Crashlytics start]_block_invoke + 617
    10  libdispatch.dylib                   0x00007fff519798cb _dispatch_client_callout + 8
    11  libdispatch.dylib                   0x00007fff5197ab02 _dispatch_once_callout + 20
    12  my-app.debug            0x000000011027b6ee -[Crashlytics start] + 131
    13  my-app.debug            0x000000011027bb04 +[Crashlytics initializeIfNeeded] + 48
    14  my-appTests             0x00000001151bbc41 __15+[Fabric with:]_block_invoke + 535
    15  libdispatch.dylib                   0x00007fff519798cb _dispatch_client_callout + 8
    16  libdispatch.dylib                   0x00007fff5197ab02 _dispatch_once_callout + 20
    17  my-appTests             0x00000001151bba24 +[Fabric with:] + 233
    18  my-appTests             0x00000001151bd992 +[Fabric autoInitialize:] + 680
    19  my-appTests             0x00000001151bd6aa __14+[Fabric load]_block_invoke + 191
    20  Foundation                          0x00007fff2590d694 -[__NSObserver _doit:] + 287
    21  CoreFoundation                      0x00007fff23d68d0c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
    22  CoreFoundation                      0x00007fff23d68185 _CFXRegistrationPost1 + 421
    23  CoreFoundation                      0x00007fff23d67ef1 ___CFXNotificationPost_block_invoke + 193
    24  CoreFoundation                      0x00007fff23e652d3 -[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1795
    25  CoreFoundation                      0x00007fff23d67846 _CFXNotificationPost + 950
    26  Foundation                          0x00007fff2590de2b -[NSNotificationCenter postNotificationName:object:userInfo:] + 59
    27  my-app.debug            0x00000001102ce2a6 +[FIRApp sendNotificationsToSDKs:] + 502
    28  my-app.debug            0x00000001102cca12 +[FIRApp configureWithName:options:] + 1410
    29  my-app.debug            0x00000001102cc34f +[FIRApp configureWithOptions:] + 143
    30  my-app.debug            0x00000001102cc29d +[FIRApp configure] + 157
    31  my-app.debug            0x000000010fd26206 $s24national_flags_ios_debug8LauncherC6launchyyF + 166
    32  my-app.debug            0x000000010fcf5394 $s24national_flags_ios_debug11AppDelegateC11application_29didFinishLaunchingWithOptionsSbSo13UIApplicationC_SDySo0m6LaunchL3KeyaypGSgtF + 100
    33  my-app.debug            0x000000010fcf5613 $s24national_flags_ios_debug11AppDelegateC11application_29didFinishLaunchingWithOptionsSbSo13UIApplicationC_SDySo0m6LaunchL3KeyaypGSgtFTo + 211
    34  UIKitCore                           0x00007fff48c0fecc -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 232
    35  UIKitCore                           0x00007fff48c1186b -[UIApplication _callInitializationDelegatesWithActions:forCanvas:payload:fromOriginatingProcess:] + 3985
    36  UIKitCore                           0x00007fff48c1742d -[UIApplication _runWithMainScene:transitionContext:completion:] + 1226
    37  UIKitCore                           0x00007fff48322a61 -[_UISceneLifecycleMultiplexer completeApplicationLaunchWithFBSScene:transitionContext:] + 122
    38  UIKitCore                           0x00007fff4882d065 _UIScenePerformActionsWithLifecycleActionMask + 83
    39  UIKitCore                           0x00007fff48323573 __101-[_UISceneLifecycleMultiplexer _evalTransitionToSettings:fromSettings:forceExit:withTransitionStore:]_block_invoke + 198
    40  UIKitCore                           0x00007fff48322f82 -[_UISceneLifecycleMultiplexer _performBlock:withApplicationOfDeactivationReasons:fromReasons:] + 296
    41  UIKitCore                           0x00007fff483233a0 -[_UISceneLifecycleMultiplexer _evalTransitionToSettings:fromSettings:forceExit:withTransitionStore:] + 818
    42  UIKitCore                           0x00007fff48322c35 -[_UISceneLifecycleMultiplexer uiScene:transitionedFromState:withTransitionContext:] + 345
    43  UIKitCore                           0x00007fff48327226 __186-[_UIWindowSceneFBSSceneTransitionContextDrivenLifecycleSettingsDiffAction _performActionsForUIScene:withUpdatedFBSScene:settingsDiff:fromSettings:transitionContext:lifecycleActionType:]_block_invoke_2 + 178
    44  UIKitCore                           0x00007fff48743415 +[BSAnimationSettings(UIKit) tryAnimatingWithSettings:actions:completion:] + 852
    45  UIKitCore                           0x00007fff4884b7c2 _UISceneSettingsDiffActionPerformChangesWithTransitionContext + 240
    46  UIKitCore                           0x00007fff48326f41 __186-[_UIWindowSceneFBSSceneTransitionContextDrivenLifecycleSettingsDiffAction _performActionsForUIScene:withUpdatedFBSScene:settingsDiff:fromSettings:transitionContext:lifecycleActionType:]_block_invoke + 153
    47  UIKitCore                           0x00007fff4884b6c5 _UISceneSettingsDiffActionPerformActionsWithDelayForTransitionContext + 84
    48  UIKitCore                           0x00007fff48326daf -[_UIWindowSceneFBSSceneTransitionContextDrivenLifecycleSettingsDiffAction _performActionsForUIScene:withUpdatedFBSScene:settingsDiff:fromSettings:transitionContext:lifecycleActionType:] + 381
    49  UIKitCore                           0x00007fff4817a968 __64-[UIScene scene:didUpdateWithDiff:transitionContext:completion:]_block_invoke + 657
    50  UIKitCore                           0x00007fff48179527 -[UIScene _emitSceneSettingsUpdateResponseForCompletion:afterSceneUpdateWork:] + 253
    51  UIKitCore                           0x00007fff4817a692 -[UIScene scene:didUpdateWithDiff:transitionContext:completion:] + 210
    52  UIKitCore                           0x00007fff48c15975 -[UIApplication workspace:didCreateScene:withTransitionContext:completion:] + 512
    53  UIKitCore                           0x00007fff4876a160 -[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:] + 361
    54  FrontBoardServices                  0x00007fff36c6091e -[FBSSceneImpl _callOutQueue_agent_didCreateWithTransitionContext:completion:] + 419
    55  FrontBoardServices                  0x00007fff36c869b1 __86-[FBSWorkspaceScenesClient sceneID:createWithParameters:transitionContext:completion:]_block_invoke.154 + 102
    56  FrontBoardServices                  0x00007fff36c6b347 -[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:] + 220
    57  FrontBoardServices                  0x00007fff36c86642 __86-[FBSWorkspaceScenesClient sceneID:createWithParameters:transitionContext:completion:]_block_invoke + 355
    58  libdispatch.dylib                   0x00007fff519798cb _dispatch_client_callout + 8
    59  libdispatch.dylib                   0x00007fff5197c292 _dispatch_block_invoke_direct + 285
    60  FrontBoardServices                  0x00007fff36cac2d9 __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 30
    61  FrontBoardServices                  0x00007fff36cabfc7 -[FBSSerialQueue _queue_performNextIfPossible] + 441
    62  FrontBoardServices                  0x00007fff36cac4d6 -[FBSSerialQueue _performNextFromRunLoopSource] + 22
    63  CoreFoundation                      0x00007fff23da1c71 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    64  CoreFoundation                      0x00007fff23da1b9c __CFRunLoopDoSource0 + 76
    65  CoreFoundation                      0x00007fff23da1374 __CFRunLoopDoSources0 + 180
    66  CoreFoundation                      0x00007fff23d9bf6e __CFRunLoopRun + 974
    67  CoreFoundation                      0x00007fff23d9b884 CFRunLoopRunSpecific + 404
    68  GraphicsServices                    0x00007fff38b5ac1a GSEventRunModal + 139
    69  UIKitCore                           0x00007fff48c19220 UIApplicationMain + 1605
    70  my-app.debug            0x000000010fcf610b main + 75
    71  libdyld.dylib                       0x00007fff519b910d start + 1
    72  ???                                 0x0000000000000007 0x0 + 7
)
libc++abi.dylib: terminating with uncaught exception of type NSException
```

`+[FIRApp sendNotificationsToSDKs:]` でクラッシュしているようです。

## 暫定的な対応

この件について、FirebaseのiOS向けQuickstartにIssueが立っていました。

[#473｜Firebase Crashlytics: Unable to run unit tests - *** Terminating app due to uncaught exception 'FABException', reason: '[Fabric] Value of Info.plist key "Fabric" must be a NSDictionary.'](https://github.com/firebase/quickstart-ios/issues/473)

`Podfile` のテスト用ターゲットに `inherit!: search_paths` を記述することで解決したケースもあるようですが、自分の場合はテスト実行中にFirebaseの構成処理を呼び出さないようにすることで暫定対応しました。

```swift
func isRunningUnitTests() -> Bool {
    return ProcessInfo.processInfo.environment["XCInjectBundleInto"] != nil
}

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    ...
    if !isRunningUnitTests() {
        FirebaseApp.configure()
    }
    ...
    return true
}
```

以上