'how to test view model protocol and UI elements of UIVIewController in iOS swift?
This is UIViewController Class below where the user will click on the button title "Run", which shows some progress on ProgressView after that random number is generated and displayed on View. Users can reset the flow again.
class ProgressViewController: UIViewController {
@IBOutlet weak var actionButton: UIButton!
@IBOutlet weak var progressView: UIProgressView!
@IBOutlet weak var resultLabel: UILabel!
var viewModel: ProgressViewModelProtocol!
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
}
func configureUI() {
setInitialStateOfElements()
}
func setInitialStateOfElements() {
actionButton.isHidden = false
actionButton.setTitle("Run", for: .normal)
progressView.isHidden = true
progressView.progress = 0
resultLabel.isHidden = true
}
func setInProgressStateOfElements() {
actionButton.isHidden = true
progressView.isHidden = false
resultLabel.isHidden = true
}
func setLoadedStateOfElements(randomValue: String) {
actionButton.isHidden = false
actionButton.setTitle("Reset", for: .normal)
progressView.isHidden = true
resultLabel.isHidden = false
resultLabel.text = randomValue
}
@IBAction func actionButtonClicked() {
viewModel.handleButtonAction()
}
}
extension ProgressViewController: ProgressViewProtocol {
func displayTheProgressValue(randomValue: String) {
self.setLoadedStateOfElements(randomValue: randomValue)
}
func updateProgressOnView(progress: Float) {
self.setInProgressStateOfElements()
self.progressView.setProgress(progress, animated: true)
}
func setTheInitialState() {
self.setInitialStateOfElements()
}
}
This is ProgressViewModel Class.
enum ProgressState {
case Initial
case InProgress
case Loaded(randomValue: String)
}
protocol ProgressViewProtocol: AnyObject {
func setTheInitialState()
func updateProgressOnView(progress: Float)
func displayTheProgressValue(randomValue: String)
}
protocol ProgressViewModelProtocol: AnyObject {
func handleButtonAction()
}
class ProgressViewModel {
var state: ProgressState {
didSet {
switch state {
case .Initial:
view.setTheInitialState()
case .InProgress:
madeSomeProgress ()
case .Loaded(let randomValue):
view.displayTheProgressValue(randomValue: randomValue)
}
}
}
init(state: ProgressState) {
self.state = state
}
weak var view: ProgressViewProtocol!
weak var coordinator : ProgressCoordinator?
func madeSomeProgress() {
let totalTime: TimeInterval = 2
let stepTime: TimeInterval = 0.1
let startDate = Date()
let cancellable = Timer.publish(every: stepTime, on: .main, in: .default)
.autoconnect()
.map { Float($0.timeIntervalSince(startDate) / totalTime) }
.sink { [weak self] progressValue in
self?.view.updateProgressOnView(progress: progressValue)
}
DispatchQueue.main.asyncAfter(deadline: .now() + totalTime) { [weak self] in
cancellable.cancel()
let randomValue = "\(Int.random(in: 1...99))"
self?.state = ProgressState.Loaded(randomValue: randomValue)
}
}
}
extension ProgressViewModel: ProgressViewModelProtocol {
func handleButtonAction() {
switch state {
case .Initial:
state = .InProgress
case .InProgress:
print("in progress")
case .Loaded:
state = .Initial
}
}
}
This is ProgressViewModelTests class where I am facing issues while writing test cases for ProgressState.
import XCTest
@testable import MysteriousApp
class ProgressViewProtocolMock: ProgressViewProtocol {
var randomValueReceived = ""
func displayTheProgressValue(randomValue: String) {
randomValueReceived = randomValue
}
func updateProgressOnView(progress: Float) {
}
func setTheInitialState() {
}
}
class ProgressViewModelTests: XCTestCase {
var viewModel: ProgressViewModel!
var view: ProgressViewProtocolMock!
override func setUp() {
viewModel = ProgressViewModel(state: .Initial)
view = ProgressViewProtocolMock()
viewModel.view = view
}
func testInitialState() {
viewModel.state = .Initial
}
func testInProgressState() {
viewModel.state = .InProgress
}
func testLoadedState() {
viewModel.state = .Loaded(randomValue: "56")
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|



