Сводка
Я создаю Observable, который генерирует события, вызывая onNext
из DispatchQueue.async
, и мой соответствующий модульный тест должен sleep(...)
, чтобы фактически получить события, даже если я используюTestScheduler
.
Подробный вопрос
Я создаю следующий Observable
, который читает события из потока gRPC.Я считаю, что gRPC здесь не так важен: просто отметьте, что я call.receive()
в цикле while
, и передайте его в onNext
.
private func createPositionObservable() -> Observable<Position> {
return Observable.create { observer in
let request = DronecodeSdk_Rpc_Telemetry_SubscribePositionRequest()
do {
let call = try self.service.subscribePosition(request, completion: { (callResult) in
if callResult.statusCode == .ok || callResult.statusCode == .cancelled {
observer.onCompleted()
} else {
observer.onError(RuntimeTelemetryError(callResult.statusMessage!))
}
})
DispatchQueue.init(label: "DronecodePositionReceiver").async {
while let responseOptional = try? call.receive(), let response = responseOptional {
observer.onNext(Position.translateFromRpc(response.position))
}
}
return Disposables.create {
call.cancel()
}
} catch {
observer.onError(error)
return Disposables.create()
}
}
.subscribeOn(scheduler)
}
Теперь я пытаюсь протестировать этот код с помощьюфункция ниже.Опять же, первый абзац касается только настройки контекста gRPC.Я считаю важным то, что:
- Я использую
TestScheduler
- Я передаю этот планировщик в gRPC (
scheduler
передается в Telemetry
и используется какsubscribeOn(scheduler)
выше) - I
sleep(2)
до подтверждения
func checkPositionObservableReceivesEvents(positions: [DronecodeSdk_Rpc_Telemetry_Position]) {
let fakeService = DronecodeSdk_Rpc_Telemetry_TelemetryServiceServiceTestStub()
let fakeCall = DronecodeSdk_Rpc_Telemetry_TelemetryServiceSubscribePositionCallTestStub()
fakeCall.outputs.append(contentsOf: positions.map{ position in createPositionResponse(position: position) })
fakeService.subscribePositionCalls.append(fakeCall)
let expectedEvents = positions.map{ position in next(1, translateRPCPosition(positionRPC: position)) }
let scheduler = TestScheduler(initialClock: 0)
let observer = scheduler.createObserver(Telemetry.Position.self)
let telemetry = Telemetry(service: fakeService, scheduler: scheduler)
let _ = telemetry.position.subscribe(observer)
scheduler.start()
sleep(2)
XCTAssertEqual(expectedEvents.count, observer.events.count)
XCTAssertTrue(observer.events.elementsEqual(expectedEvents, by: { (observed, expected) in
observed.value == expected.value
}))
}
Если я не sleep(...)
, мои утверждения не выполняются и observer.events.count
не получает события.Такое ощущение, что утверждение произойдет до того, как будут выпущены события.
Как мне с этим справиться?