During unit test, I would like to temporary mock the default timezone to specific country. This is what I do currently, by using global variable.
import Foundation
var _TIME_ZONE_FOR_UNIT_TEST: TimeZone? = nil
extension TimeZone {
static func current() -> TimeZone {
if let _TIME_ZONE_FOR_UNIT_TEST = _TIME_ZONE_FOR_UNIT_TEST {
return _TIME_ZONE_FOR_UNIT_TEST
} else {
return TimeZone.current
}
}
}
func testToDayResolutionInCuba() throws {
let cubaTimeZone = TimeZone(identifier: "America/Havana")!
_TIME_ZONE_FOR_UNIT_TEST = cubaTimeZone
defer {
_TIME_ZONE_FOR_UNIT_TEST = nil
}
...
// ReminderUtils.toDayResolution is depending on TimeZone.current()
let timestampWithoutTime = ReminderUtils.toDayResolution(timeMillis)
Although it works, I do not like such a way as
if
checkIs there a better way for me to perform unit test for a specific timezone?
This solution doesn't work on iOS 17, as Timezone.current
no longer reaches to NSTimeZone.systemTimeZone
in order to swizzle it.
TimeZone
is a direct wrapper over Objective-C's NSTimeZone
, and TimeZone.current
corresponds to NSTimeZone.systemTimeZone
.
Thus, you can mock/stub NSTimeZone.systemTimeZone
with any mocking framework. This will help you get rid of the nasty if
from your codebase.