Unit Testing NotificationCenter in Swift

Dave Poirier
Swift2Go
Published in
2 min readMar 13, 2021
Photo by Maxwell Nelson on Unsplash

When writing unit tests for Swift applications, it is inevitable that at some point you will need to confirm that a Notification is properly observed or generated. — We are not talking of Push Notifications here, we are talking a NotificationCenter.default.post(name: …, object: …)

Before proceeding forward, you should be familiar with the following concepts:

  • Basic Swift project in Xcode (how to build, run, etc)
  • Xcode Unit Tests (what they are, how they work)
  • Using NotificationCenter to observe and post notifications

Below we will be creating a protocol CrendentialsValidator and its implementation SimpleCredentialsValidator, then we will implement a few unit tests to confirm that our implementation works as intended and posts a notification userLoggedIn when the credentials are validated.

Tutorials covering this topic usually suggest mocking the NotificationCenter or creating a custom class to send/observe notification. We are going to take a different approach here by injecting the Notification.Name values via an InjectableNotifications struct and using the default NotificationCenter.

One advantage of this approach is forward compatibility with the NotificationCenter class with a lesser risk of forgetting to override functions. It is also less code thus fewer chances of introducing bugs.

Let’s begin by defining our CredentialsValidator protocol:

And our InjectableNotifications struct:

With the protocol and struct defined, let’s now implement our SimpleCredentialsValidator class which we will be testing next:

We created an extremely simple validator which only confirms that a value is defined. If a value is provided, it will create a User object and post a userLoggedIn notification. We need to define our User struct:

Then in our Dependency Injection registration code, we could so something like this to tie these together:

With most of the production code in place, let’s create our unit tests. We will begin by creating an extension to our InjectableNotifications struct to generate unique notification names for each test. In the Unit Test target, we create InjectableNotifications+UnitTest.swift:

Now, we create our first unit test case to confirm our SimpleCrendentialsValidator can indeed accept a defined string as a valid user:

Now that our unit tests are able to confirm the notifications are properly posted (or not), we have the peace of mind of ensuring that:

  • In the future if we change the Notification.Name associated to the userLoggedIn event, that our code will automatically work
  • Since we are using the NotificationCenter itself we know all of its method are defined without our implementation needing to re-implement any of its methods.
  • We can easily mock UIKit/UIScene/UIApplication notifications by allocating associated entries in our InjectableNotifications struct.

I hope you found this tutorial helpful. And I look forward to what else you all come up with!

--

--

Dave Poirier
Swift2Go

Senior iOS Developer | Mobile Security And Reliability Specialist