-
Notifications
You must be signed in to change notification settings - Fork 416
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bug: Cannot return nil for generic type T, when T is an interface #513
Comments
This is a workaround to get the test working with the current version of mockery: thingBuilder.On("Build").Return(func() Thing { return nil }, errors.New("some error")) |
Possible fix: Generate the following code in all non-error cases, instead of the current v := ret.Get(0)
if !reflect.ValueOf(&v).Elem().IsZero() && !reflect.ValueOf(v).IsZero() {
r0 = v.(T)
}
This also requires an addition of (The second check may not be strictly necessary, I was just trying to match the behavior of the code that mockery currently generates. It seems to work fine with just |
Even just putting |
Hi I've had the same issue and changing the generated code to this makes this usecase work:
I'm not familiar with the code on this project so it would take me a while to create a PR to add this, if I have time I'll look into it an create a PR with a proposition. |
|
Interface values can be assigned nil in go. That's their zero value. (You can also assign nil of a concrete type that implements the interface, cast that to the interface type, and return it. The difference is that calling a method on the nil interface panics, but calling a method in the second scenario will actually call the concrete type's implementation, with a nil receiver. The distinction probably isn't important here, for the purpose of generating mock code; you'd likely only be returning nil when error is non-nil anyway, and callers should be checking for that.) |
I understand that, but in this particular case: thingBuilder.On("Build").Return(nil, errors.New("some error"))
Another case why |
I'm not understanding the problem here. The only thing that fails is the type conversion inside the mock, which can be avoided by checking for nil first. What the caller does with the nil interface is up to them. |
Ah okay, on first glance I misinterpreted what was happening. Once thing to note is that using the thingBuilder.EXPECT().Build().RunAndReturn(func() (Thing, error) { return nil, nil }) To be honest, this is the cleanest way to handle this because the core issue is that when you do To be honest, this is one of the warts of mockery: the fact that we have to store expected arguments and return types inside var r0 T
var r1 error
if rf, ok := ret.Get(0).(func() (T, error)); ok {
return rf()
}
if rf, ok := ret.Get(0).(func() T); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(T)
} And this is kind of the same thing you suggested in #513 (comment). Going back to the post you made almost 2 (!) years ago: v := ret.Get(0)
if !reflect.ValueOf(&v).Elem().IsZero() && !reflect.ValueOf(v).IsZero() {
r0 = v.(T)
} This seems kind of redundant? |
Yep, I was seriously overthinking it in that first reply. Just a simple "v != nil" check is fine, no need for reflection at all. |
Also made those comments before #538 was merged. RunAndReturn should just work at this point. |
…rams As referenced on vektra#513 Types using generic typed interface params, should allow nil values on return
As referenced on vektra#513 Types using generic typed interface params, should allow nil values on return
Hello everyone, I've a fix for the issue mentioned here, the PR's been linked in the thread. Hope it helps |
As referenced on vektra#513 Types using generic typed interface params, should allow nil values on return
As referenced on vektra#513 Types using generic typed interface params, should allow nil values on return
As referenced on vektra#513 Types using generic typed interface params, should allow nil values on return
Description
For the interfaces
I'd like to mock
Builder
behavior asBut I get an error like:
Shouldn't mockery know that
Thing
is an interface and soBuilder[Thing].Build()
should be able to return(nil, error)
?Mockery Version
Golang Version
Installation Method
Expected Behavior
Can mock generic return types as nil when they are in fact interfaces.
Actual Behavior
Tests panic
The text was updated successfully, but these errors were encountered: