Golang:如何测试使用时间的函数,Now()?[duplicate]

ddhy6vgd  于 2023-02-01  发布在  Go
关注(0)|答案(1)|浏览(122)
    • 此问题在此处已有答案**:

Is there an easy way to stub out time.Now() globally during test?(10个答案)
Golang testing programs that involves time(1个答案)
昨天关门了。
我有一个函数,用于计算自特定时间戳以来的天数,其中时间戳来自外部API(在API返回的json中解析为字符串)
我一直在关注这篇关于如何测试使用时间的函数的文章。Now():https://medium.com/go-for-punks/how-to-test-functions-that-use-time-now-ea4f2453d430
我的函数如下所示:

type funcTimeType func() time.Time // per suggested in article

func ageOfReportDays(dateString string, funcTime funcTimeType) {
    
    // date string will look like this:
    //"2022-08-30 09:05:27.567995"

    parseLayout := "2006-01-02 15:04:05.000000"

    t, err := time.Parse(parseLayout, dateString)
    if err != nil {
        fmt.Printf("Error parsing datetime value %v: %w", timeStr, err)
    }

    days := int(time.Since(t).Abs().Hours() / 24)
    //fmt.Println(days)
    return days, nil
}

正如您所看到的,我没有在实际函数中使用funcTime funcTimeType,正如本文中所指出的,因为我不知道如何使用它来实现函数。
我希望运行的单元测试如下所示:

func Test_ageOfReportDays(t *testing.T) {
    t.Run("timestamp age in days test", func(t *testing.T) {
        parseLayout := "2006-01-02 15:04:05.000000"
        dateString := "2022-08-30 09:05:27.567995" // example of recent timestamp 
        mockNow := func() time.Time {
            fakeTime, _ := time.Parse(parseLayout, "2023-01-20 09:00:00.000000")
            return fakeTime
        }
        // now I want to use "fakeTime" to spoof "time.Now()" so I can test my function
        got: ageOfReportDays(dateString, mockNow)
        expected: 152
        if got != expected {
            t.Errorf("expected '%d' but got '%d'", expected, got)
      }
}

很明显,我的代码和文章作者的代码在逻辑上并不完全一致。有没有一个好的方法可以让我根据文章建议的模拟time.now()的方式,为这个函数编写一个单元测试?

xqnpmsa8

xqnpmsa81#

您已经非常接近了。将time.Since(t)更改为funcTime().Sub(t)可能会让您通过终点线。
来自time软件包文档:
time.Since返回从t开始经过的时间。它是time.Now().Sub(t)的简写。
示例函数:

import (
    "fmt"
    "time"
)

const parseLayout = "2006-01-02 15:04:05.000000"

type funcTimeType func() time.Time // per suggested in article

func ageOfReportDays(dateString string, funcTime funcTimeType) (int, error) {
    t, err := time.Parse(parseLayout, dateString)
    if err != nil {
        return 0, fmt.Errorf("parsing datetime value %v: %w", dateString, err)
    }

    days := int(funcTime().Sub(t).Hours() / 24)
    //fmt.Println(days)
    return days, nil
}

和一个测试:

import (
    "testing"
    "time"
)

func Test_ageOfReportDays(t *testing.T) {
    t.Run("timestamp age in days test", func(t *testing.T) {
        dateString := "2022-08-30 09:05:27.567995" // example of recent timestamp
        mockNow := func() time.Time {
            fakeTime, _ := time.Parse(parseLayout, "2023-01-20 09:00:00.000000")
            return fakeTime
        }
        // now I want to use "fakeTime" to spoof "time.Now()" so I can test my function
        got, _ := ageOfReportDays(dateString, mockNow)
        expected := 142
        if got != expected {
            t.Errorf("expected '%d' but got '%d'", expected, got)
        }
    })
}

相关问题