Is there a way to mock the viewmodels of an application that uses SwiftUI and Combine? I always find articles about mocking services used by the viewmodel but never mocking a viewmodel itself.
I tried to create protocols for each viewmodel. Problem: the @Published wrapper cannot be used in protocols. It seems like there are no solutions...
Thanks for your help
Using a protocol type as @ObservableObject
or @StateObject
would not work. Inheritance might be a solution (like Jake suggested), or you could go with a generic solution.
protocol ContentViewModel: ObservableObject {
var message: String { get set }
}
Your view model would be simple.
final class MyViewModel: ContentViewModel {
@Published var message: String
init(_ message: String = "MyViewModel") {
self.message = message
}
}
On the other hand, your views would be more complex using a constrained generic.
struct ContentView<Model>: View where Model: ContentViewModel {
@ObservedObject
var viewModel: Model
var body: some View {
VStack {
Text(viewModel.message)
Button("Change message") {
viewModel.message = "🥳"
}
}
}
}
The disadvantage is that you have to define the generic concrete type when using the view --- inheritance could avoid that.
// your mock implementation for testing
final class MockViewModel: ContentViewModel {
@Published var message: String = "Mock View Model"
}
let sut = ContentView<MockViewModel>(viewModel: MockViewModel())