我刚刚开始学习 RxSwift 并尝试构建一个示例应用程序来练习这些概念。
我编写了一个 QuestionViewModel,它从 QuestionOps 类加载问题列表。QuestionOps 有一个 getQuestions 函数,它返回 Single<[Question]>。
我面临的问题是,如何在测试 QuestionViewModel 时模拟 QuestionOps 类的行为。
public class QuestionsListViewModel {
public var questionOps: QuestionOps!
private let disposeBag = DisposeBag()
private let items = BehaviorRelay<[QuestionItemViewModel]>(value: [])
public let loadNextPage = PublishSubject<Void>()
public var listItems: Driver<[QuestionItemViewModel]>
public init() {
listItems = items.asDriver(onErrorJustReturn: [])
loadNextPage
.flatMapFirst { self.questionOps.getQuestions() }
.map { $0.map { QuestionItemViewModel($0) } }
.bind(to: items)
.disposed(by: disposeBag)
}
}
public class QuestionOps {
public func getQuestions() -> Single<[Question]> {
return Single.create { event -> Disposable in
event(.success([]))
return Disposables.create()
}
}
}
我创建了这个 MockQuestionOps 用于测试目的:
public class MockQuestionOps : QuestionOps {
//MARK: -
//MARK: Responses
public var getQuestionsResponse: Single<[Question]>?
public func getQuestions() -> Single<[Question]> {
self.getQuestionsResponse = Single.create { event -> Disposable in
return Disposables.create()
}
return self.getQuestionsResponse!
}
}
在我的测试用例中,我正在执行以下操作:
/// My idea here is to test in following maner:
/// - at some point user initates loading
/// - after some time got network response with status true
func testLoadedDataIsDisplayedCorrectly() {
scheduler = TestScheduler(initialClock: 0)
let questionsLoadedObserver = scheduler.createObserver([QuestionItemViewModel].self)
let qOps = MockQuestionOps()
vm = QuestionsListViewModel()
vm.questionOps = qOps
vm.listItems
.drive(questionsLoadedObserver)
.disposed(by: disposebag)
// User initiates load questions
scheduler.createColdObservable([.next(2, ())])
.bind(to: vm.loadNextPage)
.disposed(by: disposebag)
// Simulating question ops behaviour of responding
// to get question request
/// HERE: -----------
/// This is where I am stuck
/// How should I tell qOps to send particular response with delay
scheduler.start()
/// HERE: -----------
/// How can I test list is initialy empty
/// and after loading, data is correctly loaded
}