我得到了这个类,我想为其编写测试:
import CoreLocation
import RxCocoa
import RxSwift
struct LocationManager {
private (set) var authorized: Driver<Bool>
private let coreLocationManager = CLLocationManager()
init() {
coreLocationManager.distanceFilter = kCLDistanceFilterNone
coreLocationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
authorized = Observable.deferred { [weak coreLocationManager] in
let status = CLLocationManager.authorizationStatus()
guard let coreLocManager = coreLocationManager else {
return Observable.just(status)
}
return coreLocManager
.rx_didChangeAuthorizationStatus
.startWith(status)
}
.asDriver(onErrorJustReturn: CLAuthorizationStatus.NotDetermined)
.map {
switch $0 {
case .AuthorizedWhenInUse:
return true
default:
return false
}
}
coreLocationManager.requestWhenInUseAuthorization()
}
}
基本上,我想根据可能的 CLAuthorizationStatuses
测试授权的 Driver
是否具有正确的值。我需要正确方向的提示,因为我不熟悉 RxSwift 的单元测试。我想我最好的选择是创建一个 CLLocationManager
的模拟,它在调用 authorizationStatus()
时返回一些 CLAuthorizationStatus ,然后我会检查授权的 Driver 的值
对吗?
感谢任何有关如何测试此 LocationManager
类的解释。
最佳答案
好的,我让它工作了。但是我不确定这是否是一个有效的解决方案。请随时在这里纠正我。
首先,我将我的 LocationManager 类更改为:
import CoreLocation
import RxCocoa
import RxSwift
struct LocationManager<T where T: LocationManagerProtocol> {
private (set) var authorized: Driver<Bool>
private let coreLocationManager = CLLocationManager()
init(type: T.Type) {
coreLocationManager.distanceFilter = kCLDistanceFilterNone
coreLocationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
authorized = Observable.deferred { [weak coreLocationManager] in
let status = type.authorizationStatus()
guard let coreLocManager = coreLocationManager else {
return Observable.just(status)
}
return coreLocManager
.rx_didChangeAuthorizationStatus
.startWith(status)
}
.asDriver(onErrorJustReturn: CLAuthorizationStatus.NotDetermined)
.map {
switch $0 {
case .AuthorizedWhenInUse:
return true
default:
return false
}
}
coreLocationManager.requestWhenInUseAuthorization()
}
}
现在基本上可以提供符合我编写的新协议(protocol)的类型 LocationManagerProtocol
。
接下来,协议(protocol)会实现 authorizationStatus
函数,这样我就可以模拟这个了。
protocol LocationManagerProtocol {
static func authorizationStatus() -> CLAuthorizationStatus
}
然后我创建了一个CLLocationManager 的扩展 来实现这个协议(protocol):
import CoreLocation
extension CLLocationManager: LocationManagerProtocol {
}
从生产代码调用: let locationManager = LocationManager(type: CLLocationManager.self)
从测试代码调用: let locationManager = LocationManager(type: AuthorizedLocationManager.self)
或 let locationManager = LocationManager(type: ForbiddenLocationManager.self)
在我的测试类中,我添加了这两个类覆盖 authorizationStatus 方法:
class AuthorizedLocationManager: LocationManagerProtocol {
static func authorizationStatus() -> CLAuthorizationStatus {
return .AuthorizedWhenInUse
}
}
class ForbiddenLocationManager: LocationManagerProtocol {
static func authorizationStatus() -> CLAuthorizationStatus {
return .Denied
}
}
我的测试用例:
func testLocationAuthorizationPermitted() {
let locationManager = LocationManager(type: AuthorizedLocationManager.self)
locationManager.authorized
.driveNext { authorized in
XCTAssertTrue(authorized)
}
.addDisposableTo(disposeBag)
}
func testLocationAuthorizationRejected() {
let locationManager = LocationManager(type: ForbiddenLocationManager.self)
locationManager.authorized
.driveNext { authorized in
XCTAssertFalse(authorized)
}
.addDisposableTo(disposeBag)
}
抱歉发了这么长的帖子。我想我会告诉你我现在是如何解决这个问题的所有信息。然而,正如我之前所说,我对此并不陌生,很想听听有关这种方法的其他意见,以及这是否是一个有效的测试场景。
关于xcode - 为 RxSwift 编写单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37965953/