Xcode 为RxSwift编写单元测试
我得到了这个类,我想为它编写测试:Xcode 为RxSwift编写单元测试,xcode,swift,unit-testing,rx-swift,Xcode,Swift,Unit Testing,Rx Swift,我得到了这个类,我想为它编写测试: import CoreLocation import RxCocoa import RxSwift struct LocationManager { private (set) var authorized: Driver<Bool> private let coreLocationManager = CLLocationManager() init() { coreLocationManager.di
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()
}
}
导入核心位置
进口RxCocoa
导入RxSwift
结构位置管理器{
专用(设置)var授权:驱动程序
私有let coreLocationManager=CLLocationManager()
init(){
coreLocationManager.distanceFilter=KCLDistanceFilterOne
coreLocationManager.desiredAccuracy=KCallocationAccuracyBestforNavigation
authorized=Observable.deferred{[weak coreLocationManager]在
let status=CLLocationManager.authorizationStatus()
guard let coreLocationManager=coreLocationManager else{
返回可观察。仅(状态)
}
返回coreLocManager
.rx_didChangeAuthorizationStatus
.startWith(状态)
}
.asDriver(onErrorJustReturn:CLAuthorizationStatus.NotDetermined)
.地图{
转换$0{
案例.授权使用:
返回真值
违约:
返回错误
}
}
coreLocationManager.RequestWhenUseAuthorization()
}
}
基本上,我想根据可能的clauthorizationstatus
测试授权的驱动程序是否具有正确的值。我需要一个正确方向的提示,因为我不熟悉RxSwift的单元测试。我想我最好的选择是创建一个模拟的CLLocationManager
,当调用authorizationStatus()
时,它会返回一些CLAuthorizationStatus,然后我会检查authorized驱动程序的值,对吗
对于如何测试这个LocationManager
类的任何解释,我们都非常感谢。看看RxSwift
是如何实现单元测试的:
至于使用模拟的CLLocationManager
,是的,依赖注入将是一种可行的方法。好的,我让它工作起来了。然而,我不确定这是否是一个有效的解决方案。请在这里纠正我
首先,我将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()
}
}
然后,我创建了CLLocationManager的扩展来实现此协议:
import CoreLocation
extension CLLocationManager: LocationManagerProtocol {
}
来自生产代码的调用:让locationManager=locationManager(类型:CLLocationManager.self)
从测试代码调用:让locationManager=locationManager(类型:AuthorizedLocationManager.self)
或者let locationManager=locationManager(类型:biddenlocationmanager.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)
}
抱歉发了这么长的邮件。我想我会告诉你我现在是如何解决这个问题的。然而,正如我之前所说的,我对这一点还不熟悉,我希望听到关于这种方法的其他意见,以及这是否是一个有效的测试场景
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)
}