Saving data in UserDefaults.standard is one of the most common ways in iOS. But it is not easy to manage the data stored in that, and we also don’t want to have shared data between App and Test target.
So the solution is easy, let’s use UserDefaults.standard in the App target and use another UserDefault object in the Test target.
let dataManager = DataManager() dataManager.getSavedName() // -> How to control the output here?
Let’s refactor it a little bit with Dependency Injection, and create another UserDefaults object. The data will be stored in another file, and will not impact the data we saved in App target.
// Keep default value as UserDefaults.standard, so we don't need to pass this parameter in App target init(userDefault: UserDefaults = UserDefaults.standard) { self.userDefaults = userDefault } funcgetSavedName() -> String? { return userDefaults.value(forKey: "SavedName") as? String } }
// App target let dataManager = DataManager() // No need to pass userDefaults parameter dataManager.getSavedName()
overridefuncsetUpWithError()throws { userDefaults = UserDefaults(suiteName: "TestingUserDefaults") // Clear all data in TestingUserDefault before each Test case userDefaults.removePersistentDomain(forName: "TestingUserDefaults") userDefaults.synchronize() // Inject TestingUserDefaults dataManager = DataManager(userDefaults: userDefaults) }
// The token will be expired after 3600s var isExpired: Bool { returnDate().timeIntervalSince1970 - issueTime > 3600 } }
let token = Token(issueTime: Date().timeIntervalSince1970) token.isExpired // How can we verify if it works?
We will have 2 test cases here:
Token is expired
Token is not expired.
So in order to verify those test cases, we need a hardcoding issueTime, and control the output of Date().timeIntervalSince1970 depend on the test cases.
We can have the testing data as below.
issueTime = 1667894582
Token is expired: Date().timeIntervalSince1970 returns 1667894582 + 3601
Token is not expired: Date().timeIntervalSince1970 returns 1667894582 + 1000
So how to control the output of Date().timeIntervalSince1970? Again, using Dependency Injection, but with a closure to generate Date().