-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Default mock of Optional.isEmpty() returns true for RETURN_DEEP_STUBS #3097
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
Conversation
private static final long serialVersionUID = -7105341425736035847L; | ||
|
||
@Override | ||
public Object answer(InvocationOnMock invocation) throws Throwable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this answer, on line 68 we already call delegate().answer()
where the delegate is ReturnsEmptyValues
. This class in turn already returns an empty optional:
mockito/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsEmptyValues.java
Lines 142 to 149 in 076e8ac
} else if (type == Optional.class) { | |
return Optional.empty(); | |
} else if (type == OptionalDouble.class) { | |
return OptionalDouble.empty(); | |
} else if (type == OptionalInt.class) { | |
return OptionalInt.empty(); | |
} else if (type == OptionalLong.class) { | |
return OptionalLong.empty(); |
Is there a different reason why we are not hitting that codepath?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Because
Optional
returns to be mockable in line 66!typeMockabilityOf(rawType, mockSettings.getMockMaker()).mockable()
. - The
delegate().answer()
would return a realOptional
, which was mentioned in the ticket not to be the right thing to return. As theRETURNS_DEEP_STUBS
also do not returndelegate().answer()
for e.g.Lists
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case I would say the delegation is not working as expected and we should fix that instead. I would like us not to reimplement the logic of returning empty values in another place, which is why we have the delegate. If that is not working properly, I consider that the bug. Can you look into fixing that while we make sure we don't break other use cases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@TimvdLippe Yes I can do that.
But just to be sure, that will also return a real Optional in the RETURNS_DEEP_STUBS
case.
So the observable behavior for the client will be different for e.g. Lists and Optionals, when using RETURNS_DEEP_STUBS
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@TimvdLippe done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't support mocking Java internal types such as Optional
. The fact that it worked by accident I consider a bug, not a feature. Therefore, while we can document it, I consider this a bug fix to fix code that should have never worked and we did not support. I don't even know if it works as we would expect it does, so who knows what the undefined behaviour is.
For all of these, we should delegate to ReturnsEmptyValues
so that we have one place where we define this. Since Collections are returned and are in the same category, they would follow as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@TimvdLippe The proposed change to use ReturnsEmptyValues
breaks multiple existing (>=12) tests.
Shall I go forward and change these tests to comply to the new behavior?
This seams like an invasive change.
Example:
org.mockitousage.basicapi.MocksSerializationTest#BUG_ISSUE_399_try_some_mocks_with_current_answers
org.mockito.internal.stubbing.defaultanswers.ReturnsGenericDeepStubsTest#will_return_default_value_on_non_mockable_nested_generic
and more...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm yes that is too many breakages unfortunately. Still, I would prefer us to not implement this same list twice. Can we come up with a way that uses both?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could delegate the check into ReturnsEmptyValue
where I extract the Optional checks into an own method, then we have the different logic, but near each other to see the differences.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@TimvdLippe Done.
a88b734
to
d8e94f1
Compare
src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsDeepStubs.java
Outdated
Show resolved
Hide resolved
…P_STUBS ReturnsDeepStubs now answers with true on Optional.isEmpty() when using RETURN_DEEP_STUBS. ReturnsDeepStubs now returns real Optionals instead of mocks. Fixes mockito#2865
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## main #3097 +/- ##
============================================
- Coverage 85.45% 85.01% -0.45%
+ Complexity 2889 2878 -11
============================================
Files 329 329
Lines 8822 8826 +4
Branches 1095 1095
============================================
- Hits 7539 7503 -36
- Misses 995 1047 +52
+ Partials 288 276 -12
☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
ReturnsDeepStubs now answers with true on Optional.isEmpty() when using RETURN_DEEP_STUBS.
ReturnsDeepStubs now returns real Optionals instead of mocks.
Fixes #2865
Checklist
including project members to get a better picture of the change
commit is meaningful and help the people that will explore a change in 2 years
Fixes #<issue number>
in the description if relevantFixes #<issue number>
if relevant