gpt4 book ai didi

swift - 如何在XCTestCase的viewModel中正确测试通过发布者更改的var

转载 作者:行者123 更新时间:2023-12-01 12:03:46 25 4
gpt4 key购买 nike

我试图在Combine框架和SwiftUI中测试一个简单的发布者。我的测试在我的 View 模型中测试了一个名为isValid的已发布 bool 。我的 View 模型还具有一个已发布的用户名字符串,当更改并变为3个字符或更多时,将为isValid分配值。这是 View 模型。我确定我不了解发布者在测试环境中的工作方式,时间安排等。在此先感谢。

public class UserViewModel: ObservableObject {
@Published var username = ""
@Published var isValid = false
private var disposables = Set<AnyCancellable>()

init() {
$username
.receive(on: RunLoop.main)
.removeDuplicates()
.map { input in
print("~~~> \(input.count >= 3)")
return input.count >= 3
}
.assign(to: \.isValid, on: self)
.store(in: &disposables)
}
}

这是我的看法,在这里并不重要
struct ContentView: View {
@ObservedObject private var userViewModel = UserViewModel()
var body: some View {
TextField("Username", text: $userViewModel.username)
}
}

这是我的测试文件和单个测试失败
class StackoverFlowQuestionTests: XCTestCase {
var model = UserViewModel()

override func setUp() {
model = UserViewModel()
}

override func tearDown() {
}

func testIsValid() {
model.username = "1"
XCTAssertFalse(model.isValid)
model.username = "1234"
XCTAssertTrue(model.isValid) //<----- THIS FAILS HERE
}

}

最佳答案

原因是 View 模型是异步的,但测试是同步的。

$username
.receive(on: RunLoop.main)
...此处的 .receive运算符在 isValid的下一个事件周期对 RunLoop.main进行最终分配
但是测试
model.username = "1234"
XCTAssertTrue(model.isValid) //<----- THIS FAILS HERE
希望 isValid将立即更改。
因此,有以下可能的解决方案:
  • 完全删除.receive运算符(在这种情况下,它是可取的,因为它是UI工作流,它始终位于主运行循环中,因此使用计划接收是多余的。
    $username
    .removeDuplicates()
    .map { input in
    print("~~~> \(input.count >= 3)")
    return input.count >= 3
    }
    .assign(to: \.isValid, on: self)
    .store(in: &disposables)

  • 结果:
    model.username = "1234"
    XCTAssertTrue(model.isValid) // << PASSED
  • 使UT等待一个事件,然后才测试isValid(在这种情况下,应记录为isValid具有故意的异步特性)
    model.username = "1234"
    RunLoop.main.run(mode: .default, before: .distantPast) // << wait one event
    XCTAssertTrue(model.isValid) // << PASSED
  • 关于swift - 如何在XCTestCase的viewModel中正确测试通过发布者更改的var,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59690913/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com