为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕容708150 2021-06-08 03:08:41
我们的部分代码是时间敏感的,我们需要能够保留一些东西,然后在 30-60 秒内释放它等等,我们可以做一个 time.Sleep(60 * time.Second)我刚刚实现了时间接口,并在测试期间使用了时间接口的存根实现,类似于这个 golang-nuts 讨论。然而,time.Now()在多个站点中被调用,这意味着我们需要传递一个变量来跟踪我们实际睡了多少时间。我想知道是否有另一种方法可以在time.Now()全球范围内进行存根。也许进行系统调用来更改系统时钟?也许我们可以编写我们自己的时间包,它基本上环绕时间包但允许我们更改它?我们目前的实现效果很好,我是一个初学者,我很想知道是否有人有其他想法?
查看完整描述

3 回答

?
撒科打诨

TA贡献1934条经验 获得超2个赞

通过实现自定义界面,您已经走上了正确的道路。我认为您使用了您发布的 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) }

和测试实现。

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


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


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


查看完整回答
反对 回复 2021-06-28
?
繁花不似锦

TA贡献1851条经验 获得超4个赞

如果您需要模拟的方法很少,例如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


查看完整回答
反对 回复 2021-06-28
  • 3 回答
  • 0 关注
  • 203 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信