2

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.

Bracken
  • 989
  • 8
  • 21
Jasiuoo
  • 41
  • 1
  • 1
  • 2
  • 1
    The choices seem pretty clear, either write the comparison manually, or use a comparator with more features like [`go-cmp`](https://pkg.go.dev/github.com/google/go-cmp/cmp) – JimB Sep 27 '21 at 19:29

1 Answers1

7

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
}

Bracken
  • 989
  • 8
  • 21