Trikalabs
  • Home
  • Best online TDD videos
  • Book Suggestions
  • About Me
  • Contact
Trikalabs
No Result
View All Result

Unit testing code with DispatchQueue

by fragi
May 13, 2021
in Unit Testing
Share on FacebookShare on Twitter

One way of testing code with DispatchQueue is by using expectations (https://developer.apple.com/documentation/xctest/asynchronous_tests_and_expectations/testing_asynchronous_operations_with_expectations) but in most of the cases it’s more clean to treat the DispatchQueue as a dependency. In those cases as almost always passing the dependency through the constructor is the ideal way. This gives us the option to make clear to a reader that this object is doing some work on a queue and also enable us to use the object with a different queue if needed.

Let’s see a typical example with a ViewController:

Swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import UIKit
 
class DispatchQueueOnViewController: UIViewController {
 
    @IBOutlet weak var someDataLabel: UILabel!
    
    init() {
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    @IBAction func didTapButton(_ sender: Any) {
        DispatchQueue.main.async {
            self.someDataLabel.text = "something loaded"
        }
    }
}

Using dependency injection we can write the above code as follows:

Swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import UIKit
 
class DispatchQueueOnViewController: UIViewController {
 
    @IBOutlet weak var someDataLabel: UILabel!
    private let dispatchQueue: DispatchQueueType
 
    init(dispatchQueue: DispatchQueueType) {
        self.dispatchQueue = dispatchQueue
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    @IBAction func didTapButton(_ sender: Any) {
        dispatchQueue.async {
            self.someDataLabel.text = "something loaded"
        }
    }
}
 
protocol DispatchQueueType {
    func async(execute work: @escaping @convention(block) () -> Void)
}
 
extension DispatchQueue: DispatchQueueType {
    func async(execute work: @escaping @convention(block) () -> Void) {
        async(group: nil, qos: .unspecified, flags: [], execute: work)
    }
}

Now in order to unit testing now the didTapButton action all we have to do is to initialize the ViewController with a test double for the DispatchQueue.

Swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import XCTest
@testable import UnitTestDispatchQueue
 
class DispatchQueueOnViewControllerTests: XCTestCase {
    
    func test_DidTapButton_setsValueOnLabel() {
        let fakeQueue = DispatchQueueFake()
        let sut = DispatchQueueOnViewController(dispatchQueue: fakeQueue)
        _ = sut.view
        
        sut.didTapButton(UIButton())
        
        XCTAssertEqual("something loaded" , sut.someDataLabel.text)
    }
}
 
final class DispatchQueueFake: DispatchQueueType {
    func async(execute work: @escaping @convention(block) () -> Void) {
        work()
    }
}
fragi

fragi

Related Posts

What is TDD?
Unit Testing

Write better Unit tests with XCTUnwrap

January 27, 2022

Testing optionals can require boilerplate code to unwrap it. It can also affect the readability of the test. Let's look...

Test static method on collaborator
Unit Testing

Test static method on collaborator

May 13, 2021

One of the main issues we are facing when we try to make an old piece of code testable is...

Dependency injection – UIViewController in Storyboard (iOS 13)
Unit Testing

Dependency injection – UIViewController in Storyboard (iOS 13)

May 13, 2021

Finally Apple (iOS 13 +) has added constructor dependency injection to Storyboards! No excuses anymore for not using DI properly...

Unit testing UIViewController LifeCycle
Unit Testing

Unit testing UIViewController LifeCycle

May 13, 2021

Unit testing UIViewController life cycle events are not a straightforward process. Let's have a look on the following view controller:...

Dependency Injection – UIViewController with a Nib file
Unit Testing

Dependency Injection – UIViewController with a Nib file

May 13, 2021

UIViewControllers are among the most used UIKit objects. As the name implies UIViewControllers are controller objects and their purpose should...

Unit Test Post Notification
Unit Testing

Unit Test Post Notification

July 19, 2019

In this article, we will see how we can test code that post notifications. Let's see our example code: ...

Next Post
Git rebase with SourceTree

Git rebase with SourceTree

Dependency injection – UIViewController in Storyboard (iOS 13)

Dependency injection - UIViewController in Storyboard (iOS 13)

Test static method on collaborator

Test static method on collaborator

  • Advertise
  • Privacy & Policy
  • Contact

© 2019 Trikalabs Ltd. All rights reserved.

No Result
View All Result
  • Home
  • About Me
  • A curated list with the best free online TDD videos
  • Book Suggestions
  • Pinner Code Club

© 2019 Trikalabs Ltd. All rights reserved.