我正在监听发布者的更改,然后在管道中异步获取一些数据并使用结果更新视图。但是,我不确定如何使其可测试。我怎样才能最好地等到期望得到满足?
struct ContentView: View {
@StateObject var viewModel = ContentViewModel()
var body: some View {
NavigationView {
List(viewModel.results, id: \.self) {
Text($0)
}
.searchable(text: $viewModel.searchText)
}
}
}
final class ContentViewModel: ObservableObject {
@Published var searchText: String = ""
@Published var results: [String] = []
private var cancellables = Set<AnyCancellable>()
init() {
observeSearchText()
}
func observeSearchText() {
$searchText
.dropFirst()
.debounce(for: 0.8, scheduler: DispatchQueue.main)
.sink { _ in
Task {
await self.fetchResults()
}
}.store(in: &cancellables)
}
private func fetchResults() async {
do {
try await Task.sleep(nanoseconds: 1_000_000_000)
self.results = ["01", "02", "03"]
} catch {
//
}
}
}
class ContentViewTests: XCTestCase {
func testExample() {
// Given
let viewModel = ContentViewModel()
// When
viewModel.searchText = "123"
// Then (FAILS - Not waiting properly for result/update)
XCTAssertEqual(viewModel.results, ["01", "02", "03"])
}
}
如果我使
fetchResults()
可用,我可以异步/等待,这适用于我的单元和快照测试,但我担心:
func testExample_Workaround() async {
// Given
let viewModel = ContentViewModel()
// When
await viewModel.fetchResults()
// Then
XCTAssertEqual(viewModel.results, ["01", "02", "03"])
}
需要通过期望异步等待,并通过发布者检查结果。
这是可能的方法。使用 Xcode 13.2 / iOS 15.2 进行测试
private var cancellables = Set<AnyCancellable>()
func testContentViewModel() {
// Given
let viewModel = ContentViewModel()
let expect = expectation(description: "results")
viewModel.$results
.dropFirst() // << skip initial value !!
.sink {
XCTAssertEqual($0, ["01", "02", "03"])
expect.fulfill()
}
.store(in: &cancelables)
viewModel.searchText = "123"
wait(for: [expect], timeout: 3)
}