Golang中的编组/解组时间对象意外失败

时间:2018-09-04 14:42:20

标签: unit-testing go

由于几个字符的原因,将编组时间对象解组失败

测试

声明以下内容:

// values
now := time.Now()
timeToJSON, _ := json.Marshal(now)
var obj time.Time
json.Unmarshal(timeToJSON, &obj)

然后执行以下测试逻辑:

if !assert.Equal(t,
    now.String(),
    obj.String()) {
    t.FailNow()
}

预期

要通过的测试,并且两个对象相等

实际

失败:

--- FAIL: TestFromJSON (0.00s)
    D:\dev2017\GO\src\ezsoft\apiserver_sdk\model\delete\deleteModel_test.go:94: 
            Error Trace:    deleteModel_test.go:94
            Error:          Not equal: 
                            expected: "2018-09-04 10:36:18.3627338 -0400 EDT m=+0.014000801"
                            actual  : "2018-09-04 10:36:18.3627338 -0400 EDT"

                            Diff:
                            --- Expected
                            +++ Actual
                            @@ -1 +1 @@
                            -2018-09-04 10:36:18.3627338 -0400 EDT m=+0.014000801
                            +2018-09-04 10:36:18.3627338 -0400 EDT
            Test:           TestFromJSON
FAIL
FAIL    ezsoft/apiserver_sdk/model/delete   1.336s
Error: Tests failed.

注意

我注意到,在检查输出时,某种程度上m=+[blah]会附加到预期/实际中。

但是,我不知道为什么,skimming RFC 3339也没有给我任何提示。

2 个答案:

答案 0 :(得分:2)

time.String()不是测试时间值的可靠方法(除非您也关心单调时钟值)。来自the docs(添加了强调):

  

func(时间)字符串

func (t Time) String() string
     

字符串返回使用格式字符串格式化的时间

"2006-01-02 15:04:05.999999999 -0700 MST"
     

如果时间具有单调时钟读数,则返回的字符串包括最后一个字段“ m =±”,其中value是单调时钟读数,格式为秒的十进制数。

     

返回的字符串用于调试;要获得稳定的序列化表示形式,请使用t.MarshalText,t.MarshalBinary或带有明确格式字符串的t.Format。

对于您的用例,最好使用time.MarshalText()的输出,而不要使用time.String()

expected, _ := now.MarshalText()
actual, _ := obj.MarshalText()

if !assert.Equal(string(expected), string(actual)) ...

答案 1 :(得分:1)

对于每个the documentationm值是单调时钟值,可以使用Truncate将其删除以进行比较,而不是出于计时目的。 m字段不匹配,因为从JSON中省略了它,它仅由time.Now()生成。

尝试这样:

// values
now := time.Now().Truncate(0)  // Truncate to remove monotonic clock portion
timeToJSON, _ := json.Marshal(now)
var obj time.Time
json.Unmarshal(timeToJSON, &obj)

添加了单调时钟偏移,以便对跨越壁钟更改(例如NTP更新,DST更改或leap秒/拖尾)的持续时间进行准确计时。