I have a class that I want to test with XCTest, and this class looks something like this:
public class MyClass: NSObject { func method() {
The class uses a singleton, which is implemented as follows:
public class SingletonClass: NSObject {
Now for the test. I want to check that method() really does what it should do, but I do not want to call the code in callMethod() (because it does some awful async / network / thread data that should not run under MyClass tests, and this will cause the test to fail).
So what I would like to do basically:
SingletonClass = MockSingletonClass: SingletonClass { override func callMethod() {
This is obviously not valid Swift, but you get the idea. How can I override callMethod() just for this particular test to make it harmless?
EDIT: I tried to solve this using the dependency injection form, but ran into big problems. I created my own init method, which will be used for tests, so that I can create my objects as follows:
let myObject = MyClass(singleton: MockSingletonClass)
and let MyClass look like this
public class MyClass: NSObject { let singleton: SingletonClass init(mockSingleton: SingletonClass){ self.singleton = mockSingleton } init() { singleton = SingletonClass.sharedInstance } func method() {
Mixing in the test code with the rest of the code is what I find a bit uncomfortable, but everything is fine. The BIG problem was that I had two singleton built this way in my project, both referencing each other:
public class FirstSingletonClass: NSObject { // Only accessible using singleton static let sharedInstance = FirstSingletonClass() let secondSingleton: SecondSingletonClass init(mockSingleton: SecondSingletonClass){ self.secondSingleton = mockSingleton } private override init() { secondSingleton = SecondSingletonClass.sharedInstance super.init() } func someMethod(){ // Use secondSingleton } } public class SecondSingletonClass: NSObject { // Only accessible using singleton static let sharedInstance = SecondSingletonClass() let firstSingleton: FirstSingletonClass init(mockSingleton: FirstSingletonClass){ self.firstSingleton = mockSingleton } private override init() { firstSingleton = FirstSingletonClass.sharedInstance super.init() } func someOtherMethod(){ // Use firstSingleton } }
This created a dead end when one of the singletones where it was first used is because the init method will wait for the init method of the other, etc ...