Skip to content

Instantly share code, notes, and snippets.

@fxm90
Last active May 9, 2022 14:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fxm90/106fd802f869d3d259d672d0416b66fa to your computer and use it in GitHub Desktop.
Save fxm90/106fd802f869d3d259d672d0416b66fa to your computer and use it in GitHub Desktop.
Example on how to elegantly test a delegate protocol.
//
// ScreenOverlayViewModel.swift
//
// Created by Felix Mau on 12.10.19.
// Copyright © 2019 Felix Mau. All rights reserved.
//
protocol ScreenOverlayViewModelDelegate: AnyObject {
func screenOverlayViewModelDidUpdate(alpha: CGFloat)
}
final class ScreenOverlayViewModel {
// MARK: - Public properties
weak var delegate: ScreenOverlayViewModelDelegate?
// MARK: - Public methods
func showOverlay() {
delegate?.screenOverlayViewModelDidUpdate(alpha: 1.0)
}
func hideOverlay() {
delegate?.screenOverlayViewModelDidUpdate(alpha: 0.0)
}
}
//
// ScreenOverlayViewModelTestCase.swift
//
// Created by Felix Mau on 12.10.19.
// Copyright © 2019 Felix Mau. All rights reserved.
//
import XCTest
final class ScreenOverlayViewModelTestCase: XCTestCase {
// MARK: - Private properties
private var delegateMock: ScreenOverlayViewModelDelegateMock!
private var viewModel: ScreenOverlayViewModel!
// MARK: - Public methods
override func setUp() {
super.setUp()
delegateMock = ScreenOverlayViewModelDelegateMock()
viewModel = ScreenOverlayViewModel()
viewModel.delegate = delegateMock
}
override func tearDown() {
viewModel = nil
delegateMock = nil
super.tearDown()
}
// MARK: - Test method `showOverlay`
func testShowOverlayShouldInformDelegateToUpdateAlphaToOne() {
// When
viewModel.showOverlay()
// Then
XCTAssertEqual(delegateMock.invokedMethod, .screenOverlayViewModelDidUpdate(alpha: 1.0))
}
// MARK: - Test method `hideOverlay`
func testHideOverlayShouldInformDelegateToUpdateAlphaToZero() {
// When
viewModel.hideOverlay()
// Then
XCTAssertEqual(delegateMock.invokedMethod, .screenOverlayViewModelDidUpdate(alpha: 0.0))
}
}
// MARK: - Mocks
private final class ScreenOverlayViewModelDelegateMock: ScreenOverlayViewModelDelegate {
// MARK: - Types
enum DelegateMethod: Equatable {
case screenOverlayViewModelDidUpdate(alpha: CGFloat)
}
// MARK: - Public properties
private(set) var invokedMethod: DelegateMethod?
// MARK: - `ScreenOverlayViewModelDelegate` Protocol
func screenOverlayViewModelDidUpdate(alpha: CGFloat) {
invokedMethod = .screenOverlayViewModelDidUpdate(alpha: alpha)
}
}
@fxm90
Copy link
Author

fxm90 commented Oct 14, 2019

In case you need to verify multiple delegate methods are called, you can change the type of the property invokedMethod to an array:

private(set) var invokedMethods = [DelegateMethod]()

and in the delegate protocol method use append(), to add all invoked methods to that array:

    func screenOverlayViewModelDidUpdate(alpha: CGFloat) {
        invokedMethods.append(
            .screenOverlayViewModelDidUpdate(alpha: alpha)
        )
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment