swift - 如何断言使用最新文本输入的可观察对象的输出
问题描述
我的视图模型上有一个属性:
let isValid: Driver<Bool>
let credentials: Driver<(String, String)>
......
credentials = .combineLatest(bindings.username, bindings.password, resultSelector: { (username, password) -> (String, String) in (username, password) })
isValid = credentials.map { username, password in username.count > 0 && password.count > 7 }
我想断言在设置isValid
有效输入时设置了正确的状态。
我的测试在下面通过,但这感觉不是测试这种情况的正确方法。
理想情况下,我想从我的字符串 as 开始""
,然后像输入它们一样传入值,这样我就可以断言默认状态已设置然后更改。
我还发现这些行:
.do(onNext: { state in
if state {
exp.fulfill()
}
})
有点“hacky”。
func test_is_valid_state_changes_when_inputs_correct_length() {
let username: Driver<String> = .of("some_user_name")
let password: Driver<String> = .of("some_user_password")
let bindings = LoginViewModel.Bindings(username: username, password: password, loginTap: .empty(), doneTap: .empty())
let sut = LoginViewModel(dependency: "", bindings: bindings)
let scheduler = TestScheduler(initialClock: 0)
let observer = scheduler.createObserver(Bool.self)
let exp = expectation(description: "isValid Event")
sut.isValid
.asObservable()
.do(onNext: { state in
if state {
exp.fulfill()
}
})
.subscribe(observer)
.disposed(by: disposeBag)
scheduler.start()
waitForExpectations(timeout: 0.5) { error in
XCTAssertNil(error)
XCTAssertEqual(observer.events.count, 1)
XCTAssertTrue(observer.events[0].value.element!) // swiftlint:disable:this force_unwrapping
}
}
解决方案
您需要使用 TestObservables 来进行所需的测试,并且不需要期望对象,因为此测试将在没有任何线程问题的情况下完成。
func test_is_valid_state_changes_when_inputs_correct_length() {
let scheduler = TestScheduler(initialClock: 0)
let username = scheduler.createHotObservable([.next(0, ""), .next(10, "h")])
let password = scheduler.createHotObservable([.next(0, ""), .next(30, "p"), .next(40, "passwor"), .next(50, "password")])
let bindings = LoginViewModel.Bindings(
username: username.asDriver(onErrorRecover: { _ in XCTFail(); return .empty() }),
password: password.asDriver(onErrorRecover: { _ in XCTFail(); return .empty() }),
loginTap: .empty(),
doneTap: .empty()
)
let disposeBag = DisposeBag()
let sut = LoginViewModel(dependency: "", bindings: bindings)
let observer = scheduler.createObserver(Bool.self)
sut.isValid
.drive(observer)
.disposed(by: disposeBag)
scheduler.start()
XCTAssertEqual(observer.events, [
.next(0, false),
.next(10, false),
.next(30, false),
.next(40, false),
.next(50, true)
])
}
推荐阅读
- html-email - 是否可以使用 mjml 设置容器或包装器宽度?
- typo3 - 如何在 TYPO3 中将压缩和连接的 CSS 移动或包含到页脚?
- python-3.x - 升级 Python 版本以运行和创建 Sagemaker Endpoint 的自定义容器
- amazon-s3 - 拒绝在框架中连接“https://s3.console.aws.amazon.com/”,因为 AWS 是“X-Frame-Options”到“拒绝”
- c# - 将巨大的项目列表作为参数传递给 SQL Server 的最高效方法是什么?
- nextcloud - 在 lxd 中捕捉 nextcloud,apparmor 失败
- python - IsADirectoryError: [Errno 21] 是一个目录:
- python - Leetcode: 14. 最长公共前缀
- c# - 使用 C# 比较两个文件夹中的文件
- database - Visual Studio 上没有模板