0

I would like to test if MyViewController has subscribed to notifications in the default NSNotificationCenter in swift.

Kaushil Ruparelia
  • 972
  • 1
  • 7
  • 22
  • 3
    Simple. Post notification and handle it. Create expectation and fulfill it in your handler. otherwise it will fail after time limit. – Shial Jan 22 '18 at 22:10

1 Answers1

1

Here is code you can drop right into a Playground. Inline comments explain what's going on.

import UIKit
import XCTest

//this is a useful helper function for delaying an action
func delay(_ delay:Double, closure:@escaping ()->()) {
    //credit: Matt Neuberg - http://stackoverflow.com/questions/24034544/dispatch-after-gcd-in-swift/24318861#24318861
    DispatchQueue.main.asyncAfter(
        deadline: DispatchTime.now() + Double(Int64(delay * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: closure)
}

class MyViewController : UIViewController {

    //you just need something you can check to verify the notification was received
    var didReceiveMyNotification = false

    override func viewDidLoad() {
        super.viewDidLoad()

        NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "myNotification"), object: nil, queue: nil) {
            notification in

            //keep track when the notification is received
            self.didReceiveMyNotification = true
        }
    }

    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}

class testMyViewController: XCTestCase {

    func testShouldSubscribeToNotification() {

        weak var expectation = self.expectation(description: "testShouldSubscribeToNotification")

        //if your view controller is in a storyboard, then do this instead
        //let viewController = UIStoryboard(name: "MyStoryboard", bundle: Bundle.main).instantiateViewController(withIdentifier: "MyViewControllerIdentifier") as! MyViewController
        let viewController = MyViewController()

        //force the view to load
        let _ = viewController.view

        //post the notification
        NotificationCenter.default.post(name: Notification.Name(rawValue: "myNotification"), object: nil, userInfo: nil)

        //wait however long is needed for the notification to get handled by view controller
        delay(0.5) {
            print("result=\(viewController.didReceiveMyNotification)")

            //if the view controller was properly subscribed, this should be true
            XCTAssertTrue(viewController.didReceiveMyNotification)
            expectation?.fulfill()
        }

        //wait for the notification to get handled before allowing the test to exit
        waitForExpectations(timeout: 1.0, handler: nil)
    }
}

//if you want to run the test in a Playground...
let myTester = testMyViewController()
myTester.testShouldSubscribeToNotification()
Mike Taverne
  • 8,358
  • 2
  • 35
  • 50