首页 > 文章列表 > 有没有一种简单的方法可以在测试期间全局删除 time.Now() ?

有没有一种简单的方法可以在测试期间全局删除 time.Now() ?

golang
303 2023-03-08

问题内容

我们的部分代码是时间敏感的,我们需要能够保留一些东西,然后在 30-60 秒内释放它等等,我们可以做一个time.Sleep(60 * time.Second)

我刚刚实现了时间接口,并且在测试期间使用了时间接口的存根实现,类似于这个 golang-nuts 讨论。

但是,time.Now()在多个站点中调用,这意味着我们需要传递一个变量来跟踪我们实际睡了多少时间。

我想知道是否有另一种方法可以在time.Now()全球范围内存根。也许进行系统调用以更改系统时钟?

也许我们可以编写自己的时间包,它基本上包含时间包但允许我们更改它?

我们目前的实现效果很好,我是一个初学者,我很想知道是否有人有其他想法?

正确答案

通过实现自定义界面,您 已经走在了正确的道路上 。我认为您使用了您发布的 golang 坚果线程中的以下建议:


type Clock interface {
  Now() time.Time
  After(d time.Duration) <-chan time.Time
}

并提供一个具体的实现

type realClock struct{}
func (realClock) Now() time.Time { return time.Now() }
func (realClock) After(d time.Duration) <-chan time.Time { return time.After(d) }

和一个测试实现。


原版的

在进行测试(或一般情况下)时更改系统时间是一个坏主意 。在执行测试时,您不知道什么取决于系统时间,并且您不想通过花费数天的调试时间来找出困难的方法。只是不要这样做。

也没有办法在全局范围内隐藏时间包 ,这样做不会做任何你不能用接口解决方案做的事情。您可以编写自己的时间包,该包使用标准库并提供切换到模拟时间库的功能以测试是否是您需要通过接口解决方案传递的时间对象。

设计和测试代码的最佳方法可能是使尽可能多的代码无状态。将您的功能拆分为可测试的无状态部分。单独测试这些组件会容易得多。此外,更少的副作用意味着更容易使代码同时运行。