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

Unit Test Post Notification

by fragi
July 19, 2019
in Unit Testing
Share on FacebookShare on Twitter

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

Swift
1
2
3
4
5
6
7
8
9
10
11
import UIKit
 
class ViewController: UIViewController {
 
    override func viewDidLoad() {
        super.viewDidLoad()
 
        NotificationCenter.default.post(Notification(name: Notification.Name("aNotification"), object: nil, userInfo: ["key": "value"]))
    }
 
}

The code in its current state, is not testable. So before we start writing our unit tests we have to bring the code in a testable state. We notice that we are calling the NotificationCenter in the viewDidLoad. Our object depends on a concrete implementation. Changing from NotificationCenter to another implementation is not straightforward. In this case, we have to stop thinking of concrete implementations but to think of what is the purpose of the NotificationCenter in our object. We are using it because we want to post a notification. By having this in mind we can capture this intent a protocol:

Swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
protocol NotificationCenterPostProtocol {
    func post(name aName: NSNotification.Name, object anObject: Any?, userInfo aUserInfo: [AnyHashable : Any]?)
}
 
extension NotificationCenter: NotificationCenterPostProtocol {}
 
class ViewController: UIViewController {
 
     var notificationCenter: NotificationCenterPostProtocol? = NotificationCenter.default //The object which is responsible for creating the viewController should set the NotificationCenter.default.
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        notificationCenter?.post(name: Notification.Name("aNotification"), object: nil, userInfo: ["key": "value"])
    }
 
}

The trick here is  that we want our  protocol to have the same method signatures as the NotificationCenter. Having the same method signatures  makes the NotificationCenter to conform to this functionality efortless.

Now our code is in a testable, so we can write our test. We will use a spy to capture the call in the post method:

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
33
34
35
import XCTest
@testable import DemoUnitTestPostNotification
 
class ViewControllerTests: XCTestCase {
 
    func test_viewDidLoad_postNotification() {
        let sut = ViewController()
        let spyNotificationCenterPost = SpyNotificationCenterPost()
        sut.notificationCenter = spyNotificationCenterPost
        
        _ = sut.view
        
        XCTAssertEqual(Notification.Name("aNotification"), spyNotificationCenterPost.notificationName)
        XCTAssertNil(spyNotificationCenterPost.object)
        XCTAssertEqual(["key": "value"], spyNotificationCenterPost.userInfo as! [String : String])
    }
 
}
 
extension ViewControllerTests {
    
    class SpyNotificationCenterPost: NotificationCenterPostProtocol {
        
        var notificationName: NSNotification.Name?
        var object: Any?
        var userInfo: [AnyHashable : Any]?
        
        func post(name aName: NSNotification.Name, object anObject: Any?, userInfo aUserInfo: [AnyHashable : Any]?) {
            self.notificationName = aName
            self.object = anObject
            self.userInfo = aUserInfo
        }
    }
 
}

 

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 code with DispatchQueue
Unit Testing

Unit testing code with DispatchQueue

May 13, 2021

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...

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...

Next Post
AWS: Integrate User Pools on iOS Apps

AWS: Integrate User Pools on iOS Apps

AWS: Integrate User Pools with Clean Architecture

AWS: Integrate User Pools with Clean Architecture

AWS: Use Amazon PinPoint to collect analytics

AWS: Use Amazon PinPoint to collect analytics

  • 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.