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

新手上路,请多包涵

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

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

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

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

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

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

原文由 samol 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 586
2 个回答

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


 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) }

和测试实施。


原来的

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

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

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

原文由 nemo 发布,翻译遵循 CC BY-SA 3.0 许可协议

如果你需要模拟的方法很少,比如 Now() ,你可以制作一个可以被测试覆盖的包变量:

 package foo

import "time"

var now = time.Now

// The rest of your code...which calls now() instead of time.Now()

然后在你的测试文件中:

 package foo

import (
    "testing"
    "time"
)

var now = func() time.Time { return ... }

// Your tests

原文由 Flimzy 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题