Making a testable singleton (with a lowercase s)
An example on how to create a testable singleton object and use property injection to replace it with a mock object during testing.
The Singleton pattern restricts the instantiation of a class to one instance.
In swift they commonly appear as a class with a private initializer and a static constant named shared, that holds an instance of itself.
The code above makes it impossible to isolate the view controller from its dependencies.
In the view controller’s loadData method, we are directly accessing a shared instance of UntestableApiClient. In testing, we would not be able to test the view controller without being impacted by the ApiClient i.e we cannot test the view controller in isolation of its dependencies.
If we re-design the api client singleton to be an open class, with a public initializer (which breaks the law of being a Singleton with a capital S), then we can mock the api client during testing. In order for this to work we also need to inject the dependency into the view controller.
TIL; true Singletons in swift cannot be tested using subclassing, but singletons (in the way that URLSession is a singleton) can be written in a way that they can be testable using subclassing and property injection