diff --git a/assert/assertion_format.go b/assert/assertion_format.go index 2d089991a..e88203538 100644 --- a/assert/assertion_format.go +++ b/assert/assertion_format.go @@ -5,6 +5,7 @@ package assert import ( http "net/http" url "net/url" + reflect "reflect" time "time" ) @@ -475,6 +476,16 @@ func JSONEqf(t TestingT, expected string, actual string, msg string, args ...int return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...) } +// Kindf asserts that the given object's kind matches the expected kind. +// +// assert.Kindf(t, reflect.String, "Hello World", "error message %s", "formatted") +func Kindf(t TestingT, expectedKind reflect.Kind, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Kind(t, expectedKind, object, append([]interface{}{msg}, args...)...) +} + // Lenf asserts that the specified object has specific length. // Lenf also fails if the object has a type that len() not accept. // @@ -667,6 +678,16 @@ func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, return NotImplements(t, interfaceObject, object, append([]interface{}{msg}, args...)...) } +// NotKindf asserts that the given object's kind does not match the unexpected kind. +// +// assert.NotKindf(t, reflect.Int, "Hello World", "error message %s", "formatted") +func NotKindf(t TestingT, unexpectedKind reflect.Kind, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotKind(t, unexpectedKind, object, append([]interface{}{msg}, args...)...) +} + // NotNilf asserts that the specified object is not nil. // // assert.NotNilf(t, err, "error message %s", "formatted") diff --git a/assert/assertion_forward.go b/assert/assertion_forward.go index d8300af73..f36db4721 100644 --- a/assert/assertion_forward.go +++ b/assert/assertion_forward.go @@ -5,6 +5,7 @@ package assert import ( http "net/http" url "net/url" + reflect "reflect" time "time" ) @@ -942,6 +943,26 @@ func (a *Assertions) JSONEqf(expected string, actual string, msg string, args .. return JSONEqf(a.t, expected, actual, msg, args...) } +// Kind asserts that the given object's kind matches the expected kind. +// +// a.Kind(reflect.String, "Hello World") +func (a *Assertions) Kind(expectedKind reflect.Kind, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Kind(a.t, expectedKind, object, msgAndArgs...) +} + +// Kindf asserts that the given object's kind matches the expected kind. +// +// a.Kindf(reflect.String, "Hello World", "error message %s", "formatted") +func (a *Assertions) Kindf(expectedKind reflect.Kind, object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Kindf(a.t, expectedKind, object, msg, args...) +} + // Len asserts that the specified object has specific length. // Len also fails if the object has a type that len() not accept. // @@ -1326,6 +1347,26 @@ func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interfac return NotImplementsf(a.t, interfaceObject, object, msg, args...) } +// NotKind asserts that the given object's kind does not match the unexpected kind. +// +// a.NotKind(reflect.Int, "Hello World") +func (a *Assertions) NotKind(unexpectedKind reflect.Kind, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotKind(a.t, unexpectedKind, object, msgAndArgs...) +} + +// NotKindf asserts that the given object's kind does not match the unexpected kind. +// +// a.NotKindf(reflect.Int, "Hello World", "error message %s", "formatted") +func (a *Assertions) NotKindf(unexpectedKind reflect.Kind, object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotKindf(a.t, unexpectedKind, object, msg, args...) +} + // NotNil asserts that the specified object is not nil. // // a.NotNil(err) diff --git a/assert/assertions.go b/assert/assertions.go index a27e70546..d08ef2a89 100644 --- a/assert/assertions.go +++ b/assert/assertions.go @@ -487,6 +487,54 @@ func IsNotType(t TestingT, theType, object interface{}, msgAndArgs ...interface{ return Fail(t, fmt.Sprintf("Object type expected to be different than %T", theType), msgAndArgs...) } +// Kind asserts that the given object's kind matches the expected kind. +// +// assert.Kind(t, reflect.String, "Hello World") +func Kind(t TestingT, expectedKind reflect.Kind, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if expectedKind == reflect.Invalid { + return Fail(t, "reflect.Invalid must not be used as expected kind", msgAndArgs...) + } + + if object == nil { + return Fail(t, "Object must not be nil", msgAndArgs...) + } + + objectKind := reflect.TypeOf(object).Kind() + if objectKind == expectedKind { + return true + } + + return Fail(t, fmt.Sprintf("Object expected to be of kind %v, but was %v", expectedKind, objectKind), msgAndArgs...) +} + +// NotKind asserts that the given object's kind does not match the unexpected kind. +// +// assert.NotKind(t, reflect.Int, "Hello World") +func NotKind(t TestingT, unexpectedKind reflect.Kind, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if unexpectedKind == reflect.Invalid { + return Fail(t, "reflect.Invalid must not be used as unexpected kind", msgAndArgs...) + } + + if object == nil { + return Fail(t, "Object must not be nil", msgAndArgs...) + } + + objectKind := reflect.TypeOf(object).Kind() + if objectKind != unexpectedKind { + return true + } + + return Fail(t, fmt.Sprintf("Object expected NOT to be of kind %v, but was %v", unexpectedKind, objectKind), msgAndArgs...) +} + // Equal asserts that two objects are equal. // // assert.Equal(t, 123, 123) diff --git a/assert/assertions_test.go b/assert/assertions_test.go index 4975f5e41..2f9bf5316 100644 --- a/assert/assertions_test.go +++ b/assert/assertions_test.go @@ -585,6 +585,81 @@ func TestNotIsType(t *testing.T) { } } +func TestKind(t *testing.T) { + mockT := new(testing.T) + + cases := []struct { + expected reflect.Kind + object interface{} + result bool + remark string + }{ + // True cases + {reflect.String, "Hello World", true, "is string"}, + {reflect.Int, 123, true, "is int"}, + {reflect.Array, [6]int{2, 3, 5, 7, 11, 13}, true, "is array"}, + {reflect.Func, Kind, true, "is func"}, + {reflect.Float64, 0.0345, true, "is float64"}, + {reflect.Map, make(map[string]int), true, "is map"}, + {reflect.Bool, true, true, "is bool"}, + {reflect.Ptr, new(int), true, "is pointer"}, + + // False cases + {reflect.String, 13, false, "not string"}, + {reflect.Int, [6]int{2, 3, 5, 7, 11, 13}, false, "not int"}, + {reflect.Float64, 12, false, "not float64"}, + {reflect.Bool, make(map[string]int), false, "not bool"}, + + // Invalid inputs + {reflect.Invalid, "string", false, "reflect.Invalid must not be used as expected kind"}, + {reflect.Ptr, nil, false, "Object must not be nil"}, + } + + for _, c := range cases { + t.Run(fmt.Sprintf("Kind(%#v, %#v)", c.expected, c.object), func(t *testing.T) { + res := Kind(mockT, c.expected, c.object) + + if res != c.result { + t.Errorf("Kind(%#v, %#v) should return %#v: %s", c.expected, c.object, c.result, c.remark) + } + }) + } +} + +func TestNotKind(t *testing.T) { + mockT := new(testing.T) + + cases := []struct { + unexpected reflect.Kind + object interface{} + result bool + remark string + }{ + // True cases + {reflect.String, 123, true, "not string"}, + {reflect.Int, "hi", true, "not int"}, + {reflect.Map, []int{1, 2}, true, "not map"}, + {reflect.Ptr, 99, true, "not pointer"}, + + // False cases + {reflect.Func, func() {}, false, "is func"}, + {reflect.Bool, false, false, "is bool"}, + + // Invalid inputs + {reflect.Invalid, "string", false, "reflect.Invalid must not be used as unexpected kind"}, + {reflect.Ptr, nil, false, "Object must not be nil"}, + } + + for _, c := range cases { + t.Run(fmt.Sprintf("NotKind(%#v, %#v)", c.unexpected, c.object), func(t *testing.T) { + res := NotKind(mockT, c.unexpected, c.object) + if res != c.result { + t.Errorf("NotKind(%#v, %#v) should return %#v: %s", c.unexpected, c.object, c.result, c.remark) + } + }) + } +} + func TestEqual(t *testing.T) { t.Parallel() diff --git a/require/require.go b/require/require.go index 23a3be780..59a29d7da 100644 --- a/require/require.go +++ b/require/require.go @@ -6,6 +6,7 @@ import ( assert "github.com/stretchr/testify/assert" http "net/http" url "net/url" + reflect "reflect" time "time" ) @@ -1189,6 +1190,32 @@ func JSONEqf(t TestingT, expected string, actual string, msg string, args ...int t.FailNow() } +// Kind asserts that the given object's kind matches the expected kind. +// +// require.Kind(t, reflect.String, "Hello World") +func Kind(t TestingT, expectedKind reflect.Kind, object interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Kind(t, expectedKind, object, msgAndArgs...) { + return + } + t.FailNow() +} + +// Kindf asserts that the given object's kind matches the expected kind. +// +// require.Kindf(t, reflect.String, "Hello World", "error message %s", "formatted") +func Kindf(t TestingT, expectedKind reflect.Kind, object interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Kindf(t, expectedKind, object, msg, args...) { + return + } + t.FailNow() +} + // Len asserts that the specified object has specific length. // Len also fails if the object has a type that len() not accept. // @@ -1675,6 +1702,32 @@ func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, t.FailNow() } +// NotKind asserts that the given object's kind does not match the unexpected kind. +// +// require.NotKind(t, reflect.Int, "Hello World") +func NotKind(t TestingT, unexpectedKind reflect.Kind, object interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotKind(t, unexpectedKind, object, msgAndArgs...) { + return + } + t.FailNow() +} + +// NotKindf asserts that the given object's kind does not match the unexpected kind. +// +// require.NotKindf(t, reflect.Int, "Hello World", "error message %s", "formatted") +func NotKindf(t TestingT, unexpectedKind reflect.Kind, object interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotKindf(t, unexpectedKind, object, msg, args...) { + return + } + t.FailNow() +} + // NotNil asserts that the specified object is not nil. // // require.NotNil(t, err) diff --git a/require/require_forward.go b/require/require_forward.go index 38d985a55..819d5c8ae 100644 --- a/require/require_forward.go +++ b/require/require_forward.go @@ -6,6 +6,7 @@ import ( assert "github.com/stretchr/testify/assert" http "net/http" url "net/url" + reflect "reflect" time "time" ) @@ -943,6 +944,26 @@ func (a *Assertions) JSONEqf(expected string, actual string, msg string, args .. JSONEqf(a.t, expected, actual, msg, args...) } +// Kind asserts that the given object's kind matches the expected kind. +// +// a.Kind(reflect.String, "Hello World") +func (a *Assertions) Kind(expectedKind reflect.Kind, object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Kind(a.t, expectedKind, object, msgAndArgs...) +} + +// Kindf asserts that the given object's kind matches the expected kind. +// +// a.Kindf(reflect.String, "Hello World", "error message %s", "formatted") +func (a *Assertions) Kindf(expectedKind reflect.Kind, object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Kindf(a.t, expectedKind, object, msg, args...) +} + // Len asserts that the specified object has specific length. // Len also fails if the object has a type that len() not accept. // @@ -1327,6 +1348,26 @@ func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interfac NotImplementsf(a.t, interfaceObject, object, msg, args...) } +// NotKind asserts that the given object's kind does not match the unexpected kind. +// +// a.NotKind(reflect.Int, "Hello World") +func (a *Assertions) NotKind(unexpectedKind reflect.Kind, object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotKind(a.t, unexpectedKind, object, msgAndArgs...) +} + +// NotKindf asserts that the given object's kind does not match the unexpected kind. +// +// a.NotKindf(reflect.Int, "Hello World", "error message %s", "formatted") +func (a *Assertions) NotKindf(unexpectedKind reflect.Kind, object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotKindf(a.t, unexpectedKind, object, msg, args...) +} + // NotNil asserts that the specified object is not nil. // // a.NotNil(err)