[英]How to test a function that gets into the main thread in Swift with RxSwift and XCTest?
I came across this problem when testing my View: 我在测试View时遇到了这个问题:
In my ViewModel I call to an asynchronous operation and when the response arrives, I use a PublishSubject
to produce a change in my View. 在我的ViewModel中,我调用一个异步操作,当响应到达时,我使用
PublishSubject
在View中进行更改。 In my View, I call DispatchQueue.main.async
in order to hide or show a button. 在我的视图中,我调用
DispatchQueue.main.async
以隐藏或显示按钮。
ViewModel 视图模型
let refreshButtons = PublishSubject<Bool>(true)
refreshButtons.onNext(true)
View 视图
model.refreshButtons.asObservable()
.subscribe(onNext: {
[unowned self] success in
self.updateButtons(success)
})
.addDisposableTo(disposable)
private func updateButtons(_ show:Bool) {
DispatchQueue.main.async{
button.isHidden = !show
}
}
Now I don't know how to unit test that refreshButtons.onNext(true)
will hide or show my button. 现在,我不知道如何对
refreshButtons.onNext(true)
将隐藏或显示我的按钮进行单元测试。
The solutions I can think of are: 我能想到的解决方案是:
How can I solve this? 我该如何解决? Thank you in advance.
先感谢您。
You could use an async expectation based on a predicate in your unit test to wait an see if the button is not hidden anymore. 您可以在单元测试中使用基于谓词的异步期望,以等待按钮不再被隐藏。
func testButtonIsHidden() {
// Setup your objects
let view = ...
let viewModel = ...
// Define an NSPredicate to test your expectation
let predicate = NSPredicate(block: { input, _ in
guard let _view = input as? MyView else { return false }
return _view.button.isHidden == true
})
// Create an expectation that will periodically evaluate the predicate
// to decided whether it's fulfilled or not
_ = expectation(for: predicate, evaluatedWith: view, handler: .none)
// Call the method that should generate the behaviour you are expecting.
viewModel.methodThatShouldResultInButtonBeingHidden()
// Wait for the
waitForExpectationsWithTimeout(1) { error in
if let error = error {
XCTFail("waitForExpectationsWithTimeout errored: \(error)")
}
}
}
Something worth noting is that the value you pass to the NSPredicate
should be a class
. 值得注意的是,您传递给
NSPredicate
的值应该是一个class
。 That is because classes are passed by reference, so value inside the predicate block will be the same as the one touched by your view model. 那是因为类是通过引用传递的,所以谓词块中的值将与视图模型所触及的值相同。 If you were to pass a
struct
or enum
though, which are passed by copy, the predicate block would receive a copy of the value as it is at the time of running the setup code, and it will always fail. 如果要传递通过副本传递的
struct
或enum
,则谓词块将在运行安装代码时按原样接收值的副本,并且它将始终失败。
If instead you prefer to use UI tests as suggested by @Randall Wang in his answer, then this post might be useful for you: " How to test UI changes in Xcode 7 ". 相反,如果您更喜欢使用@Randall Wang在其答案中建议的UI测试,则此文章可能对您有用:“ 如何在Xcode 7中测试UI更改 ”。 Full disclosure, I wrote that post.
完全公开,我写了那个帖子。
First of all, You don't need test private method 首先,您不需要测试私有方法
If you want to test if the button is hidden or not,try UI testing 如果要测试按钮是否隐藏,请尝试进行UI测试
here is the WWDC of UI testing. 这是UI测试的WWDC。
https://developer.apple.com/videos/play/wwdc2015/406/ https://developer.apple.com/videos/play/wwdc2015/406/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.