+ [AVURLAsset isPlayableExtendedMIMEType:]在单元测试时表现不同

时间:2014-01-12 00:01:34

标签: ios unit-testing avfoundation

在我的应用中,调用[AVURLAsset isPlayableExtendedMIMEType:@"video/mp4; codecs=\"avc1.64001F, mp4a.40.2\""]会返回YES,这是预期的。

如果我在单元测试中运行完全相同的代码,则返回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\""], @"");
}

第一个断言通过,但第二个断言失败。

为什么在单元测试和应用程序中这种行为会有所不同?

1 个答案:

答案 0 :(得分:43)

在对+[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函数尝试读取MediaValidator.plist框架内的MediaToolbox文件。 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);