Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xcode 为RxSwift编写单元测试_Xcode_Swift_Unit Testing_Rx Swift - Fatal编程技术网

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)
}