0
0
iOS Swiftmobile~7 mins

Unit testing ViewModels in iOS Swift

Choose your learning style9 modes available
Introduction

Unit testing ViewModels helps ensure your app's logic works correctly before showing anything on screen. It catches mistakes early and makes your app more reliable.

When you want to check if your ViewModel correctly processes data from a service.
When you want to verify that your ViewModel updates its properties as expected after an action.
When you want to make sure your ViewModel handles errors properly.
When you want to test your app's logic without running the full user interface.
Syntax
iOS Swift
import XCTest
@testable import YourApp

final class YourViewModelTests: XCTestCase {
  var viewModel: YourViewModel!

  override func setUp() {
    super.setUp()
    viewModel = YourViewModel()
  }

  override func tearDown() {
    viewModel = nil
    super.tearDown()
  }

  func testExample() {
    // Arrange
    // Act
    // Assert
  }
}

Use setUp() to prepare your ViewModel before each test.

Use tearDown() to clean up after each test.

Examples
Check that the initial title is an empty string.
iOS Swift
func testInitialValue() {
  XCTAssertEqual(viewModel.title, "")
}
Test that calling updateTitle changes the title property.
iOS Swift
func testUpdateTitle() {
  viewModel.updateTitle("Hello")
  XCTAssertEqual(viewModel.title, "Hello")
}
Verify the ViewModel sets an error flag when loading data fails.
iOS Swift
func testErrorHandling() {
  viewModel.loadDataWithError()
  XCTAssertTrue(viewModel.hasError)
}
Sample App

This example shows a simple CounterViewModel with a count property. The tests check the initial count, increment behavior, and reset behavior.

iOS Swift
import XCTest

final class CounterViewModel {
  private(set) var count = 0

  func increment() {
    count += 1
  }

  func reset() {
    count = 0
  }
}

final class CounterViewModelTests: XCTestCase {
  var viewModel: CounterViewModel!

  override func setUp() {
    super.setUp()
    viewModel = CounterViewModel()
  }

  override func tearDown() {
    viewModel = nil
    super.tearDown()
  }

  func testInitialCountIsZero() {
    XCTAssertEqual(viewModel.count, 0)
  }

  func testIncrementIncreasesCount() {
    viewModel.increment()
    XCTAssertEqual(viewModel.count, 1)
  }

  func testResetSetsCountToZero() {
    viewModel.increment()
    viewModel.reset()
    XCTAssertEqual(viewModel.count, 0)
  }
}
OutputSuccess
Important Notes

Keep your ViewModel logic simple to make testing easier.

Use @testable import to access internal properties for testing.

Write one test per behavior to keep tests clear and focused.

Summary

Unit testing ViewModels helps catch bugs early by checking app logic without UI.

Use XCTest framework with setUp() and tearDown() to prepare tests.

Write small tests that check one thing at a time for clear results.