- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有一个 View 模型,其行为由 Observable.interval
控制。本质上,它会在每个 next
上更新一个计时器标签,并在一段时间后更新另一个值。
一个修剪过的例子:
class WorkoutViewModel {
private var _oneSecondTimer: Observable<Int> {
return Observable<Int>.interval(1, scheduler: MainScheduler.instance)
}
private let _exerciseRemainingTime: Variable<Int> = Variable(20)
func setupBehaviour() {
_oneSecondTimer.subscribeNext() { [unowned self] _ in
self._exerciseRemainingTime.value -= 1
if self._exerciseRemainingTime.value == 0 {
self.progressToNextExercise()
}
}
}
}
我想对此进行测试,以观察事件发生的时间和 _exerciseRemainingTime
的值。
有没有办法使用 TestScheduler
来模拟 _oneSecondTimer
会计时的虚拟时间?
最佳答案
是的,看看这个具有您正在寻找的行为的简单测试:https://github.com/ReactiveX/RxSwift/blob/b3f4bf1/Tests/RxSwiftTests/Tests/Observable+TimeTest.swift#L496
交换TestScheduler
对于 MainScheduler
,我建议您将其作为依赖项注入(inject)。
另外,检查 _exerciseRemainingTime
的值, 你需要删除 private
.但是,我不建议测试您类(class)的内部结构。删除 private
是你是的标志。相反,如果您要注入(inject)一个负责执行 progressToNextExercise
的对象,然后您可以测试它是否收到了前进到下一个练习的调用。您只需在测试期间传递该对象的测试版本,就像您对 TestScheduler
所做的那样。对于调度程序。这将消除制作 _exerciseRemainingTime
的需要公开测试它,甚至知道它。
然而,忽略 _exerciseRemainingTime
的可见性为了这个问题的主要目的,这就是我对调度程序的意思:
WorkoutViewModel.swift
class WorkoutViewModel {
private var _oneSecondTimer: Observable<Int> {
return Observable<Int>.interval(1, scheduler: scheduler)
}
// not `private` anymore. also, a computed property
var _exerciseRemainingTime: Observable<Int> {
return self._oneSecondTimer.map { i in
20 - i
}
}
// injected via `init`
private let scheduler: SchedulerType
init(scheduler: SchedulerType) {
self.scheduler = scheduler
}
}
WorkoutViewModelTest.swift
func testExerciseRemainingTime() {
let scheduler = TestScheduler(initialClock: 0)
let res = scheduler.start(0, subscribed: 0, disposed: 23) {
WorkoutViewModel(scheduler: scheduler)._exerciseRemainingTime
}
let correct = [
next(1, 20), // output .Next(20) at 1 second mark
next(2, 19), // output .Next(19) at 2 second mark
next(3, 18),
next(4, 17),
next(5, 16),
next(6, 15),
next(7, 14),
next(8, 13),
next(9, 12),
next(10, 11),
next(11, 10),
next(12, 9),
next(13, 8),
next(14, 7),
next(15, 6),
next(16, 5),
next(17, 4),
next(18, 3),
next(19, 2),
next(20, 1),
next(21, 0),
next(22, -1),
]
XCTAssertEqual(res.events, correct)
}
需要考虑的几个注意事项:
为了让测试调度程序订阅和处理,我删除了 subscribeNext
从 View 模型。我认为这无论如何都会改进它,因为您应该订阅 View Controller 并且只使用 View 模型为您提供 Observable
.这避免了 View 模型需要处理包和管理 Disposable
的生命周期。
你真的应该考虑公开一些比 _exerciseRemainingTime
更不“内部”的东西.也许像 currentExercise: Observable<ExerciseEnum>
,内部基于 _exerciseRemainingTime
.这样,您的 View Controller 就可以订阅并执行简单的与 View Controller 相关的工作,以进入下一个练习。
此外,为了简化测试,您可以注入(inject) 20
变量到 View 模型中,以便在测试中你可以提供更小的东西,比如 3
然后 correct
只需要几个元素的长度。
关于ios - 如何测试 RxSwift Observable.interval 进度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38497874/
我尝试使用 RxSwift 作为依赖项创建一个名为 MyLib 的库,它使用 cocoapod 命令 pod lib create。但是,以下代码不起作用。 import UIKit import M
我是 RxSwift 的新手。很新。通常要在没有 Rx 的情况下链接你,你将下一个函数放在一个完成闭包中。我的同事告诉我改用 flatmap 或我们的 concatmap 版本,但从未给我一个例子。有
我创建了一个使用 RxSwift、RxCocoa 和其他第三方框架的自定义框架。自定义框架正确编译,但当我添加到应用程序时,它崩溃并出现以下错误: dyld: Library not loaded:
我会尽可能简短:我们启动了完整的 RxSwift 应用程序,但我们的协调员开始不知所措,难以维护和扩展,因此我们正在重新设计他们以不使用 RxSwift,现在我们不知道如何使用它们以及保存它们的位置。
我正在使用 RxSwift 和 MVVM 实现一个简单的地址 UITableView。我像这样在我的 View Controller 中创建了一个绑定(bind)。 viewModel.address
ReactiveX.io documentation使用 AnonymousDisposable,它在 RxSwift 2.x 中,但在 RxSwift 3.0 中是一个未解析的标识符。我应该改用什么
我有一个应用程序使用 MVP与 Coordinator图案。 当子协调器发送事件时,我希望我的 AppCoordinator递归调用一个方法,根据一些 SessionState 选择下一个协调器. 该
上下文:我的团队正在开始一个新的中型 Swift 项目(大约 20 MM),我正在考虑在 RxSwift 中开发它.我的一位经理怀疑,他曾经在 上的调试方面有过不好的经历。响应式(Reactive)编
嘿,我在 HackingWithSwift 教程中学到了如何使用 Combine 发出链接的网络请求(请参阅下面的代码)。现在我将使用 RXSwift 构建相同的逻辑,但我不知道如何像在 Combin
我正在尝试进行几个 API 调用并填充领域数据库。 一切正常。但是,当我尝试运行 performSegue()在 subscribe()方法引发异常,通知我不能在后台线程上执行此操作,这是完全合理的。
假设我有 Int 数组: var items = [1, 2, 3, 4, 5] 以及一个接受 Int 参数并基于它发送网络请求的函数: func sendRequest(argument: Int
我有一个文本字段,它有 2 个验证规则:最小数量的字符和字母数字字符。 我希望能够向用户展示他在错误标签中做错了什么,但问题是,如果我将文本字段绑定(bind)到两个规则,它可能会令人毛骨悚然,因为一
我试图在选择表行时在后台执行复杂的计算,但它卡住了 UI。请查看我的代码并告诉我可能有什么问题。 tableView.rx .modelSelected(Sring.self) .fl
我正在尝试构建一个计时器,该计时器从15秒开始,递减计数到0。 事情是,我想根据事件将计时器更新2秒。 到目前为止,这是我尝试做的事情: struct ViewModel { struct I
我正在使用该领域作为后端。使用RxSwift,我可以在DB表中观察到某些列(它跟踪未决状态)。得到事件后,我切换到另一个Serial计划表,以将列的值设置为flatMap块中的Progress状态(返
我对响应式(Reactive)编程很陌生,所以我仍然很难理解它是如何工作的。 我正在尝试做的事情:当用户点击 signUpButton (signUpTrigger) 时,会触发多个 observab
以下是与问题39类似的示例:http://reactivex.io/learnrx/ 我正在尝试将方法调用search(query: String)转换为这些调用的序列。 他们通过创建一个Variab
我有两个 Single 值,它们包含同一对象的数组。我想合并它们并应用 map 并将它们作为单个返回。可能吗? 所以我有这个: func fetchTripList(type: TripType) -
使用 RxSwift,假设我有一个包含整数可观察值的 A 类 class A: { let count: Observable } 以及 A 的可观察对象集合 let data: Observ
我想转换一个我已经完全接收的 ViewModel。该应用程序计算算术表达式。 ViewModel 有两个字符串,一个带有“逻辑”符号,将发送到表达式求值器以获取结果,另一个带有其他符号的“演示”字符串
我是一名优秀的程序员,十分优秀!