I’m trying to be proactive about writing an iOS app in a test-driven manner. However, I’m stumped as to how to test a method that is to interact with real system files. For those familiar with iOS, I’m writing to the NSUserDefaults
file.
Here’s my set-up: I have a singleton called AppState
that I am using to record when data downloaded from the Internet was last synced locally. Other classes can update the dateLastSynced
property of AppState
. I am overriding the setDateLastSynced
method to save that update to the system so it’s persisted between opening and closing the app:
- (void)setDateLastSynced:(NSDate *)dateLastSynced
{
// update instance variable with new value
_dateLastSynced = dateLastSynced;
// store change to NSUserDefaults
[[NSUserDefaults standardUserDefaults] setObject:dateLastSynced forKey:APP_STATE_DATE_LAST_SYNCED_KEY];
[[NSUserDefaults standardUserDefaults] synchronize];
}
I’d like to write a test that verifies that setDateLastSynced
is working correctly – but I’m not sure how to do that without overwriting data already saved to the system in NSUserDefaults
.
5
You have to mock or emulate, and you have two very good reasons to do so.
-
You have to mock or emulate whatever parts of the system your code interacts with, precisely because:
- You don’t want to alter the system, and
-
You don’t want your tests to depend on something as uncontrollable as the system.
Yes, your emulation will not be perfect; yes, you will in fact be modelling your knowledge and assumptions about how the system works; and that’s perfectly fine. You are essentially taking a spec and restating it in code: nothing wrong with that. The spec in this case is written by the creators of the operating system and not by you.
-
You have to mock or emulate everything that deals with time, even your own stuff.
- You have to be able to set the emulated clock time to a certain fake date, pretend that files are created/modified, and then check their creation/modification date and make sure it is the fake date, and all this without of course changing the system clock.
- You also have to be able to check that a certain date in the future is correctly set, or that something happens at that moment in time, all during the execution of a single test, without having to wait for real time to advance.