XCTest 失败并出现异常“非 UI 客户端无法自动暂停”
Posted
技术标签:
【中文标题】XCTest 失败并出现异常“非 UI 客户端无法自动暂停”【英文标题】:XCTest fails with with exception 'Non-UI clients cannont be autopaused' 【发布时间】:2015-07-30 16:46:31 【问题描述】:我正在尝试将 CLLocationManager 创建为具有默认参数的单音:
+ (GeolocationService *)defaultGeolocationService
static GeolocationService *_defaultGeolocationService = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^
_defaultGeolocationService = [[GeolocationService alloc] init];
[_defaultGeolocationService initLocationManager];
);
return _defaultGeolocationService;
- (void)initLocationManager
self.locationManager = [CLLocationManager new];
self.locationManager.delegate = self;
self.locationManager.pausesLocationUpdatesAutomatically = YES;
[self.locationManager requestAlwaysAuthorization];
测试如下:
- (void)testInitWithDefaultsSettings
GeolocationService *defaultGeolocationService = [GeolocationService defaultGeolocationService];
XCTAssertTrue(defaultGeolocationService.settings.autoPause, @"autoPause");
我得到一个例外: *** 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“非 UI 客户端无法自动暂停”
我应该怎么做才能使这个测试工作?
【问题讨论】:
我猜苹果不会对自己的代码进行单元测试。 :( 或者拼写检查,想想看。 【参考方案1】:问题在于以下行
self.locationManager.pausesLocationUpdatesAutomatically = YES;
无法在未运行 UI 的应用程序上设置此属性(不知道为什么,我找不到任何有关它的文档)。
在初始化GeoLocationService
和设置self.locationManager.pausesLocationUpdatesAutomatically
之前,您可能需要在测试中进行一些检查以确保UI 已加载。
【讨论】:
另外,self.locationManager.allowsBackgroundLocationUpdates
会导致错误提示 Invalid parameter not satisfying: !stayUp || CLClientIsBackgroundable(internal->fClient) || _CFMZEnabled() (NSInternalInconsistencyException).
这是可以理解的,因为这些是与 UI 设备关联的属性。【参考方案2】:
我搜索了一些简单快速的解决方案来避免它,我找到了一些解决这个问题的方法我认为你有三个解决方案:
- 简单的:
为测试目标创建一个预处理器宏。但这取决于你有多少宏,如果你滥用它可能会使代码管理复杂化。
- 中一:
您知道所有单元测试都在模拟器上运行,所以为什么不尝试一下
#if !(TARGET_IPHONE_SIMULATOR)
但是您会告诉我,您也希望在模拟器上运行应用程序,如果您只这样做,您将无法在模拟器中的应用程序启动案例中使用该属性。
那么为什么不添加一个关于了解 XPCServiceName 正在运行的补充测试,如下所示:
NSString *serviceName = [NSProcessInfo processInfo].environment[@"XPC_SERVICE_NAME"];
BOOL amITesting = ([serviceName rangeOfString:@"xctest"].location != NSNotFound);
所以使用 #if !(TARGET_IPHONE_SIMULATOR) && !amITesting 你可以使用你的
self.locationManager.pausesLocationUpdatesAutomatically = YES;
测试会通过。
- 第三个:
我不喜欢这个解决方案,但我也写了它,这是猴子解决方案...如果您不想添加预处理器宏,请添加 try catch 并且测试也会通过。但我不建议你使用那个。
我希望它会有所帮助。
【讨论】:
【参考方案3】:这是对单元测试和其他非 UI 进程的限制,原因只有 Apple 知道。这是我正在使用的解决方案:
let serviceName = ProcessInfo.processInfo.environment["XPC_SERVICE_NAME"]
let testing = serviceName?.hasSuffix("xctest") ?? false
if !testing
locationManager.pausesLocationUpdatesAutomatically = true
【讨论】:
以上是关于XCTest 失败并出现异常“非 UI 客户端无法自动暂停”的主要内容,如果未能解决你的问题,请参考以下文章
Objective-C 协议在 XCTest 中选择器失败,但在应用程序中失败 [重复]
Cordova + XCTest 导致“架构 i386 的未定义符号”
XCTest:由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'参数'测试“不能为零”。