Skip to content

IsType is inconvenient to use, should be generic #1805

@AlisCode

Description

@AlisCode

Description

The current API of require.IsType is the following :
func require.IsType(t require.TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}).

As far as I'm aware, this requires me to create an instance of my target type (expectedType)
Example : require.IsType(t, Person{}, hopefullyAValueOfTypePerson)

The problem I see with this is that I can pass in a value of any type, making my test imprecise. I'm not asserting that my value is of an expected concrete type, I'm asserting that the types of expectedType and object are similar.

On top of that, some of us like to have stronger guarantees on exhaustiveness of structures, namely using a go lint such as exhaustruct. This makes the API very impractical to use, as now to assert the type of my value, I need to instantiate and exhaustively declare fields that in fact have no meaning, since they're never used.

Example :

require.IsType(t, Person{ age: 20, name: "Roger" }, hopefullyAValueOfTypePerson)
//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^ those fields are never used  

My current workaround is to do something like this :

_, ok := hopefullyAValueOfTypePerson.(Person)
require.True(t, ok, "Value is not a Person")

Proposed solution

I suggest something like require.IsType, but generic over any kind of type T. Signature : func require.IsOfType[T any](t require.TestingT, object interface{}, msgAndArgs ...interface{}).

I suggest implementing a new function because :

  • There are definitely cases where I find it useful to check that two values have the same type
  • Generics are a controversial topic in Go, I think folks would likely prefer to have both options
  • Changing the signature would be a breaking change. Even worse, it might silently break because the function has a variadic argument.

Here's an example implementation leveraging the workaround I described above :

func IsOfType[T any](t *testing.T, value any) {
	_, ok := value.(T)
	require.True(t, ok, "Value is not of the required type")
}

Example usage :

hopefullyAValueOfTypePerson := Person { age: 25, value: "Alice" }
require.IsOfType[Person](t, hopefullyAValueOfTypePerson)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementgenericspkg-assertChange related to package testify/assertpkg-requireChange related to package testify/require

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions