【发布时间】:2021-10-28 02:01:04
【问题描述】:
在单元测试期间,我想临时模拟特定国家/地区的默认时区。这就是我目前所做的,通过使用全局变量。
应用代码
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)
虽然可行,但我不喜欢这样的方式
- 使用了全局变量
-
if检查的额外运行时成本
我是否有更好的方法对特定时区执行单元测试?
【问题讨论】:
-
如果应用通过
TimeZone.current获取时区,那么测试的方法就是模拟TimeZone。 -
该应用使用自定义
TimeZone.current()(不是TimeZone.current),以便我们可以完全控制返回的内容。您能否详细说明我们如何“模拟”TimeZone? -
我是说使用
current。 ——你明白什么是嘲讽吗? “如果”只在应用程序启动时发生一次。如果这是我们只使用真实时区的应用程序。如果这是一个测试,我们使用具有相同接口的模拟对象,以便您可以控制从current返回的内容。 -
更改方法签名,以便您可以注入时区,并将
.current作为默认值。然后在单元测试中你可以注入你想要测试的任何区域,这也将使你的测试更加灵活。 -
或者更改方法签名,以便您可以注入类似 TimeZone 的对象,
.current消息可以发送到该对象;在真正的应用程序中是 TimeZone,但在测试中它将是你的模拟。 — 但是,如果您需要详细的帮助,您需要从您的应用程序代码中提供实际的详细信息。例如,如果目标是测试ReminderUtils.toDayResolution(timeMillis),您需要向我们展示该方法。
标签: ios swift unit-testing