testify icon indicating copy to clipboard operation
testify copied to clipboard

Correct way to assert.Equal structs that contain functions pointers

Open bLuka opened this issue 4 years ago • 4 comments

Hello,

I'm having troubles comparing objects indirectly referencing function pointers.

For the reference, here's a minimal example:

package main

import (
        "testing"

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

type s struct {
        f func()
}

func TestAssert(t *testing.T) {
        var f = func() {}
        var obj = s{f}

        assert.Equal(t, obj, obj)
}

Testing this code leads to this error:

--- FAIL: TestAssert (0.00s)
    main_test.go:17: 
                Error Trace:    main_test.go:17
                Error:          Not equal: 
                                expected: main.s{f:(func())(0x571380)}
                                actual  : main.s{f:(func())(0x571380)}
                            
                                Diff:
                Test:           TestAssert

In my specific case, this function pointer field comes from a private nested structure I don't have the ability to manipulate.

Is there a way to compare structures indirectly embedding a function pointer?

bLuka avatar Jan 13 '22 19:01 bLuka

As is mentioned in equal's docs functions are only equal if they are both nil. Looking in the source of the reflect package, any further comparison is apparently not possible in Go.

Unfortunately it looks like you'll need to compare each non-function field individually. If you need to check the function fields then you'll probably need to test code which calls them for state.

brackendawson avatar Jan 14 '22 10:01 brackendawson

As is mentioned in equal's docs functions are only equal if they are both nil. Looking in the source of the reflect package, any further comparison is apparently not possible in Go.

From what I got, it is not possible to just ignore function pointers, then? I saw github.com/google/go-cmp/cmp allows this by passing options. Is there an equivalent using only testify?

By the way, #535 mentions switching from reflect to go-cmp. It could also solve the issue.

Unfortunately it looks like you'll need to compare each non-function field individually.

It's quite complicated in this very specific case, where the function pointer appears in a 3-levels nested private struct.

bLuka avatar Jan 14 '22 11:01 bLuka

It will definitely be worth considering this case when switching to go-cmp, so thanks for linking the issues, hopefully that's picked up. It would almost certainly be something for a testify v2 release, which has been proposed but I'm not sure it's coming any time soon as the maintainers of this project seem quite stretched.

I'm fairly certain there isn't a way to do this using only testify. 😔

brackendawson avatar Jan 14 '22 12:01 brackendawson

I've been having the same problem.

OscarVanL avatar Apr 21 '22 11:04 OscarVanL