package main
import (
"fmt"
"testing"
"unsafe"
"github.com/stretchr/testify/assert"
)
func Test(t *testing.T) {
var (
nilChan chan struct{}
nilFunc func()
nilInterface any
nilMap map[int]int
nilPointer *int
nilSlice []int
nilUnsafePointer unsafe.Pointer
)
fmt.Println("\nEqual")
fmt.Println(assert.Equal(t, nil, nilChan)) // false
fmt.Println(assert.Equal(t, nil, nilFunc)) // false, cannot take func type as argument
fmt.Println(assert.Equal(t, nil, nilInterface)) // true !
fmt.Println(assert.Equal(t, nil, nilMap)) // false
fmt.Println(assert.Equal(t, nil, nilPointer)) // false
fmt.Println(assert.Equal(t, nil, nilSlice)) // false
fmt.Println(assert.Equal(t, nil, nilUnsafePointer)) // false
fmt.Println("\nEqualValues")
fmt.Println(assert.EqualValues(t, nil, nilChan)) // false
fmt.Println(assert.EqualValues(t, nil, nilFunc)) // false
fmt.Println(assert.EqualValues(t, nil, nilInterface)) // true !
fmt.Println(assert.EqualValues(t, nil, nilMap)) // false
fmt.Println(assert.EqualValues(t, nil, nilPointer)) // false
fmt.Println(assert.EqualValues(t, nil, nilSlice)) // false
fmt.Println(assert.EqualValues(t, nil, nilUnsafePointer)) // false
fmt.Println("\nExactly")
fmt.Println(assert.Exactly(t, nil, nilChan)) // false, Types expected to match exactly
fmt.Println(assert.Exactly(t, nil, nilFunc)) // false, Types expected to match exactly
fmt.Println(assert.Exactly(t, nil, nilInterface)) // true !
fmt.Println(assert.Exactly(t, nil, nilMap)) // false, Types expected to match exactly
fmt.Println(assert.Exactly(t, nil, nilPointer)) // false, Types expected to match exactly
fmt.Println(assert.Exactly(t, nil, nilSlice)) // false, Types expected to match exactly
fmt.Println(assert.Exactly(t, nil, nilUnsafePointer)) // false, Types expected to match exactly
fmt.Println("\nNotEqual")
fmt.Println(assert.NotEqual(t, nil, nilChan)) // true
fmt.Println(assert.NotEqual(t, nil, nilFunc)) // false, cannot take func type as argument
fmt.Println(assert.NotEqual(t, nil, nilInterface)) // false !
fmt.Println(assert.NotEqual(t, nil, nilMap)) // true
fmt.Println(assert.NotEqual(t, nil, nilPointer)) // true
fmt.Println(assert.NotEqual(t, nil, nilSlice)) // true
fmt.Println(assert.NotEqual(t, nil, nilUnsafePointer)) // true
fmt.Println("\nNotEqualValues")
fmt.Println(assert.NotEqualValues(t, nil, nilChan)) // true
fmt.Println(assert.NotEqualValues(t, nil, nilFunc)) // true
fmt.Println(assert.NotEqualValues(t, nil, nilInterface)) // false !
fmt.Println(assert.NotEqualValues(t, nil, nilMap)) // true
fmt.Println(assert.NotEqualValues(t, nil, nilPointer)) // true
fmt.Println(assert.NotEqualValues(t, nil, nilSlice)) // true
fmt.Println(assert.NotEqualValues(t, nil, nilUnsafePointer)) // true
// ------------------------------------------------------------------------------------------
fmt.Println("\nEqual with typed nil")
fmt.Println(assert.Equal(t, (chan struct{})(nil), nilChan)) // true
fmt.Println(assert.Equal(t, (func())(nil), nilFunc)) // false, cannot take func type as argument
fmt.Println(assert.Equal(t, (map[int]int)(nil), nilMap)) // true
fmt.Println(assert.Equal(t, (*int)(nil), nilPointer)) // true
fmt.Println(assert.Equal(t, []int(nil), nilSlice)) // true
fmt.Println(assert.Equal(t, (unsafe.Pointer)(nil), nilUnsafePointer)) // true
fmt.Println("\nEqualValues with typed nil")
fmt.Println(assert.EqualValues(t, (chan struct{})(nil), nilChan)) // true
fmt.Println(assert.EqualValues(t, (func())(nil), nilFunc)) // true
fmt.Println(assert.EqualValues(t, (map[int]int)(nil), nilMap)) // true
fmt.Println(assert.EqualValues(t, (*int)(nil), nilPointer)) // true
fmt.Println(assert.EqualValues(t, []int(nil), nilSlice)) // true
fmt.Println(assert.EqualValues(t, (unsafe.Pointer)(nil), nilUnsafePointer)) // true
fmt.Println("\nExactly with typed nil")
fmt.Println(assert.Exactly(t, (chan struct{})(nil), nilChan)) // true
fmt.Println(assert.Exactly(t, (func())(nil), nilFunc)) // false, cannot take func type as argument
fmt.Println(assert.Exactly(t, (map[int]int)(nil), nilMap)) // true
fmt.Println(assert.Exactly(t, (*int)(nil), nilPointer)) // true
fmt.Println(assert.Exactly(t, []int(nil), nilSlice)) // true
fmt.Println(assert.Exactly(t, (unsafe.Pointer)(nil), nilUnsafePointer)) // true
fmt.Println("\nNotEqual with typed nil")
fmt.Println(assert.NotEqual(t, (chan struct{})(nil), nilChan)) // false
fmt.Println(assert.NotEqual(t, (func())(nil), nilFunc)) // false, cannot take func type as argument
fmt.Println(assert.NotEqual(t, (map[int]int)(nil), nilMap)) // false
fmt.Println(assert.NotEqual(t, (*int)(nil), nilPointer)) // false
fmt.Println(assert.NotEqual(t, []int(nil), nilSlice)) // false
fmt.Println(assert.NotEqual(t, (unsafe.Pointer)(nil), nilUnsafePointer)) // false
fmt.Println("\nNotEqualValues with typed nil")
fmt.Println(assert.NotEqualValues(t, (chan struct{})(nil), nilChan)) // false
fmt.Println(assert.NotEqualValues(t, (func())(nil), nilFunc)) // false
fmt.Println(assert.NotEqualValues(t, (map[int]int)(nil), nilMap)) // false
fmt.Println(assert.NotEqualValues(t, (*int)(nil), nilPointer)) // false
fmt.Println(assert.NotEqualValues(t, []int(nil), nilSlice)) // false
fmt.Println(assert.NotEqualValues(t, (unsafe.Pointer)(nil), nilUnsafePointer)) // false
// ------------------------------------------------------------------------------------------
fmt.Println("\nGO ==")
fmt.Println(nilChan == nil) // true
fmt.Println(nilFunc == nil) // true
fmt.Println(nilInterface == nil) // true
fmt.Println(nilMap == nil) // true
fmt.Println(nilPointer == nil) // true
fmt.Println(nilSlice == nil) // true
fmt.Println(nilUnsafePointer == nil) // true
fmt.Println("\nNil")
fmt.Println(assert.Nil(t, nilChan)) // true
fmt.Println(assert.Nil(t, nilFunc)) // true
fmt.Println(assert.Nil(t, nilInterface)) // true
fmt.Println(assert.Nil(t, nilMap)) // true
fmt.Println(assert.Nil(t, nilPointer)) // true
fmt.Println(assert.Nil(t, nilSlice)) // true
fmt.Println(assert.Nil(t, nilUnsafePointer)) // true
fmt.Println("\nNotNil")
fmt.Println(assert.NotNil(t, nilChan)) // false
fmt.Println(assert.NotNil(t, nilFunc)) // false
fmt.Println(assert.NotNil(t, nilInterface)) // false
fmt.Println(assert.NotNil(t, nilMap)) // false
fmt.Println(assert.NotNil(t, nilPointer)) // false
fmt.Println(assert.NotNil(t, nilSlice)) // false
fmt.Println(assert.NotNil(t, nilUnsafePointer)) // false
}
Hi!
The using of
ObjectsAreEqual-based functions with untypednildoesn't make sense for any non-interface types, because ofexpectedandactualare interfaces:As a consequence,
Equal,EqualValuesandExactlywill always fail:And
NotEqualandNotEqualValueswill always pass:The right way is to use typed
nil:But this is verbose and we also see inconsistency of functions when working with
nilFunc.Better to just use
Nil/NotNil:Full snippet:
https://go.dev/play/p/ClGstUJWkYB
Details
Example of bug/typo in testify:
testify/mock/mock_test.go
Line 765 in db8608e
(
call.WaitForis(<-chan time.Time)(nil)).Covered by testifylint#nil-compare.