2014-01-12 10 views
13

私のアプリで[AVURLAsset isPlayableExtendedMIMEType:@"video/mp4; codecs=\"avc1.64001F, mp4a.40.2\""]を呼び出すと、YESが返されます。+ユニットのテスト時に[AVURLAsset isPlayableExtendedMIMEType:]の動作が異なります

単体テストで全く同じコードを実行すると、NOが返されます。

iOS 7.0を実行しているiPhone Retina(4インチ)シミュレータで、アプリとユニットテストの両方をXcode 5.0.2で実行します。

- (void) testPlayableExtendedMIMEType 
{ 
    XCTAssertTrue([AVURLAsset class], @""); 
    XCTAssertTrue([AVURLAsset isPlayableExtendedMIMEType:@"video/mp4; codecs=\"avc1.64001F, mp4a.40.2\""], @""); 
} 

最初のアサートは成功しますが、2番目のアサートは失敗します。

ユニットテストとアプリでこの動作が異なるのはなぜですか?

答えて

42

+[AVURLAsset isPlayableExtendedMIMEType:]の実装方法をリバースエンジニアリングしたところ、問題の原因が見つかりました。ここで

は、それが何をしているかのスタックトレースです:

frame #0: 0x01b2861e CoreMedia`CelestialGetModelSpecificName 
frame #1: 0x01b2885a CoreMedia`CelestialCFCreatePropertyListFromBundleIdentifier + 11 
frame #2: 0x00050039 AVFoundation`__33+[AVURLAsset _avfValidationPlist]_block_invoke_0 + 39 
frame #3: 0x02e99014 libdispatch.dylib`_dispatch_client_callout + 14 
frame #4: 0x02e8b09f libdispatch.dylib`dispatch_once_f + 57 
frame #5: 0x02e8b061 libdispatch.dylib`dispatch_once + 31 
frame #6: 0x00050006 AVFoundation`+[AVURLAsset _avfValidationPlist] + 49 
frame #7: 0x00050664 AVFoundation`+[AVURLAsset isPlayableExtendedMIMEType:] + 64 

CelestialCFCreatePropertyListFromBundleIdentifier機能はMediaToolbox枠組み内MediaValidator.plistファイルを読み込もうとします。 plistファイルの場所は、装置のモデル名によって異なります。 iOS 7シミュレータ用に異なるMediaValidator.plistファイルがあります。

MediaToolbox.framework 
|-- J1 
| `-- MediaValidator.plist 
|-- K93 
| `-- MediaValidator.plist 
|-- N41 
| `-- MediaValidator.plist 
`-- N94 
    `-- MediaValidator.plist 

アプリケーションを実行する場合、CelestialGetModelSpecificName関数N41i.e. iPhone 5を返します。
単体テストを実行すると、CelestialGetModelSpecificName関数はN88つまりiPhone 3GSを返します。ご覧のとおり、MediaToolboxフレームワーク内にはN88というディレクトリが存在しないため、最終的には+[AVURLAsset isPlayableExtendedMIMEType:]が失敗します。

CelestialGetModelSpecificName関数を詳しく見ると、解決策が明らかです。シミュレータは、どのデバイスがシミュレートされているかを知るために、環境変数IPHONE_SIMULATOR_CLASSを読み取ります。 IPHONE_SIMULATOR_CLASS環境変数が設定されていない場合、デフォルトでハードコードされたN88の値になります。

テストをパスするには、ユニットテストランナーが自動的に設定しないので、IPHONE_SIMULATOR_CLASSという環境変数を手動でN41に手動で設定する必要があります。

setenv("IPHONE_SIMULATOR_CLASS", "N41", 0); 
関連する問題