使用`assert.Equal`断言函数来比较包含`time.Time`对象的某个接口。

huangapple go评论77阅读模式
英文:

Go assert.Equal some interface with time.Time object inside

问题

我正在尝试检查返回的数据是否与期望值相等。

这是我的函数:

func extractData(payload string) (interface{}, time.Time, error) {

	eventTime := gjson.Get(payload, "data.eventDateTime").String()

	dateTime, err := time.Parse("2006-01-02T15:04:05-07:00", eventTime)
	if err != nil {
		return nil, time.Time{}, fmt.Errorf("日期时间错误:%w", err)
	}

	body := data.Body{
		EventTime: dateTime,
	}

	return body, dateTime, nil
}

这是我为它编写的单元测试:

func TestExtractData(t *testing.T) {

	tests := []struct {
		Name           string
		Payload        string
		ExpectedOutput interface{}
	}{
		{
			Name:    "test-2",
			Payload: `{"data":"2020-11-02T10:44:48+01:00"}`,
			ExpectedOutput: data.Body{
				EventTime: time.Date(2020, 11, 2, 10, 44, 48, 0, time.FixedZone("CET", 3600)),
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.Name, func(t *testing.T) {
			data, _, _ := extractData(tt.Payload)
			assert.Equal(t, tt.ExpectedOutput, data)
		})
	}
}

测试失败,输出如下:

{ 2020-11-02 10:44:48 +0100 CET} 不等于 { 2020-11-02 10:44:48 +0100 CET}

我认为问题在于TimeZone,但我在编写测试代码时遇到了困难。

我不想使用time.Equal进行测试,因为我的data.Body并不总是包含eventTime元素。

我尝试了以下方法(通过临时使用非接口类型):

if !tt.ExpectedOutput.EventTime.Equal(data.EventTime) {
    // 抛出错误
}

它可以工作。

我还尝试了:

if !reflect.DeepEqual(tt.ExpectedOutput.EventTime, data.EventTime) {
    t.Errorf("extractData() 输出 = %v,期望值 = %v", data, tt.ExpectedOutput)
}

上面的代码失败了。

英文:

I am trying to check if the returned data equals the expectation

Here is my function:

func extractData(payload string) (interface{}, time.Time, error) {

	eventTime := gjson.Get(payload, "data.eventDateTime").String()

	dateTime, err := time.Parse("2006-01-02T15:04:05-07:00", eventTime)
	if err != nil {
		return nil, time.Time{}, fmt.Errorf("Date Time Error: %w", err)
	}

	body := data.Body{
		EventTime: dateTime,
	}

	return body, dateTime, nil
}

This is the unit test I wrote for it:

func TestExtractData(t *testing.T) {

	tests := []struct {
		Name           string
		Payload        string
		ExpectedOutput interface{}
	}{
		{
			Name:    "test-2",
			Payload: "{\"data\":\"2020-11-02T10:44:48+01:00\"}",
			ExpectedOutput: data.Body{
				EventTime: time.Date(2020, 11, 2, 10, 44, 48, 0, time.FixedZone("CET", 3600)),
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.Name, func(t *testing.T) {
			data, _, _ := extractData(tt.Payload)
			assert.Equal(t, tt.ExpectedOutput, data)
		})
	}
}

The test is failing, it outputs:

{ 2020-11-02 10:44:48 +0100 CET} does not equal { 2020-11-02 10:44:48 +0100 CET}

I believe the problem is in TimeZone, but I struggles to write the test code.

I don't want to test it using time.Equal, because my data.Body does not always contains the eventTime element.

I tried (by temporary use type not interface):

if !tt.ExpectedOutput.EventTime.Equal(data.EventTime) {
    //throw error
}

and it works.

I also i tried:

if !reflect.DeepEqual(tt.ExpectedOutput.EventTime, data.EventTime) {
    t.Errorf("extractData() output = %v, want = %v",data,tt.ExpectedOutput)
}

The code above fails.

答案1

得分: 5

你部分正确,时区可能导致表示相同时间的两个time.Time实例无法相等。另外,自Go 1.9以来,time.Time还包括了墙上时间,以确保所有比较都是安全的,因此time.Time字面量(例如你的ExpectedOutput字段)将不包含这个墙上时间,所以它们是“不同的”。

你最好的解决方案可能是使用assert.WithinDuration()来比较时间(我假设你正在使用github.com/stretchr/testify/assert):

package kata

import (
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
)

func TestTime(t *testing.T) {
	format := "2006-01-02 15:04:05.999999999 -0700 MST"
	time1 := time.Now()
	time2, err := time.Parse(format, time1.Format(format))
	assert.NoError(t, err)
	t.Log(time1)
	t.Log(time2)
	assert.Equal(t, time1, time2)             // 失败
	assert.WithinDuration(t, time1, time2, 0) // 通过
}

英文:

You're partially correct that the time zone can make two time.Time instances representing the same time fail equality. It can also be that because since go 1.9, time.Time also includes wall time to make all comparisons safe, time.Time literals such as your ExpectedOutput field will never contain this wall time, so are "different".

Your best solution is probably to compare the time using assert.WithinDuration() (I assume you are using github.com/stretchr/testify/assert?):

package kata

import (
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
)

func TestTime(t *testing.T) {
	format := "2006-01-02 15:04:05.999999999 -0700 MST"
	time1 := time.Now()
	time2, err := time.Parse(format, time1.Format(format))
	assert.NoError(t, err)
	t.Log(time1)
	t.Log(time2)
	assert.Equal(t, time1, time2)             // fails
	assert.WithinDuration(t, time1, time2, 0) // passes
}

huangapple
  • 本文由 发表于 2021年9月28日 00:36:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/69350229.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定