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
ClassCastExceptions with JDK9 javac #357
Comments
This problem is also the cause for #304 |
Closing this issue as it seems to be resolved. |
I don't think this is fixed, both of the examples in the original report still fail with Full repro: https://gist.github.com/cushon/b5c5e3995e9ad68ed3df8fd8626daf09
|
Thanks, I check this out prior to release. |
Sorry - do you mean that you verified it's fixed at head, or that you will take another look before the next release? If it's the second one, do you mind re-opening the issue to make sure it doesn't get lost? I'm seeing the same behaviour at head. |
@cushon I think it's more that we'll look at it ;) Typically using
@raphw I think we should not delay 2.0 for that one, JDK9 is not yet out. We can still release fixes later. |
@cushon I have just completed testing Mockito against Java 9 and everything works as expected. The examples that you provide work without any problems. Thinking about how this would work, also makes sense. If not configured to return a different value, Mockito returns Did you test a recent version? |
What about |
Ah, of course. Sorry for that, I did another mistake in my test. This problem is actually already reproduceable on recent versions of Java 8. |
Ok, I have now finally looked into this in detail. There are three scenarios:
|
@TimvdLippe it has not been fixed, I turned the repro into a unit test in #664. Those tests fail in the jdk9 branch:
|
That sounds good to me. I skipped the original @Test
public void generic_return_type_checkcast() throws Throwable {
class Super<T> {
T get() {
return null;
}
}
class Sub extends Super<Boolean> {}
Sub sub = Mockito.mock(Sub.class, Answers.RETURNS_SMART_NULLS);
Mockito.when(sub.get()).thenReturn(true);
assertTrue(sub.get());
}
|
Careful as |
We might be able to get around these issues with a solution like #643 |
Note that this also fails with Eclipse's Java compiler (running under a Java 8 JRE) in Eclipse Neon (4.5), with the same ClassCastException. |
As said, there is not much we can do. The information of the required type lies outside of the class we instrument. We simply do not have this information available. I am afraid that this chained mocking is something we cannot fully support and you will have to mock your method chanes manually to supply this information. |
@raphw Thank you! Well, does it mean that mockito will never work with Java 9? Omg, it's an epic disaster... :( |
Added MockUtils with interfaces that help creating Scannable mocks that also implement another interface for combinations not naturally found in production code. See Mockito issue mockito/mockito#357, which is probably the cause why these used to pass on JDK 8.
Added MockUtils with interfaces that help creating Scannable mocks that also implement another interface for combinations not naturally found in production code. See Mockito issue mockito/mockito#357, which is probably the cause why these used to pass on JDK 8.
Only when returning automatic mocks from mocks with generic return types, maybe we should add a warning for this to make the error more intuitive. |
This commit builds under both JDK8 and JDK9 in Travis CI. Minus a couple of caveats, it fixes the JDK9 build with various changes: Version Bumps - Update to Gradle 4.2.1 for full compatibility with JDK9 - Bump asciidoctor plugin^[1] - Bump Mockito^[2] and Jacoco to their latest JDK9-compatible versions - Bump AssertJ to 3.8.0^[3] - Bump Kotlin Gradle Plugin to 1.5.51^[4] [1] Asciidoctor Caveat: *********************** In JDK9, don't build the PDF as no compatible combination of asciidoctorJ-pdf could be found... [2] Tests Adaptation, Mockito Caveats: ************************************** Fix scan tests that use mocks of non-Scannable PARENTs/ACTUALs Added MockUtils with interfaces that help creating Scannable mocks that also implement another interface for combinations not naturally found in production code. See Mockito issue mockito/mockito#357, which is probably the cause why these used to pass on JDK 8. [3] AssertJ Caveat: ******************* Added workaround to an AssertJ issue in Java 8, see: assertj/assertj#1046 [4] Kotlin Caveats: ******************* - Fixed building of Javadoc under JDK9 polluted by Kotlin classes that are deemed invalid by the Java 9 doclet. (these used to be ignored in Java 8) - Dokka is not building, so we exclude kdocZip (and thus dokka) under JDK9 (see Kotlin/dokka#220)
This commit builds under both JDK8 and JDK9 in Travis CI. Minus a couple of caveats, it fixes the JDK9 build with various changes: Version Bumps - Update to Gradle 4.2.1 for full compatibility with JDK9 - Bump asciidoctor plugin^[1] - Bump Mockito^[2] and Jacoco to their latest JDK9-compatible versions - Bump AssertJ to 3.8.0^[3] - Bump Kotlin Gradle Plugin to 1.5.51^[4] [1] Asciidoctor Caveat: *********************** In JDK9, don't build the PDF as no compatible combination of asciidoctorJ-pdf could be found... [2] Tests Adaptation, Mockito Caveats: ************************************** Fix scan tests that use mocks of non-Scannable PARENTs/ACTUALs Added MockUtils with interfaces that help creating Scannable mocks that also implement another interface for combinations not naturally found in production code. See Mockito issue mockito/mockito#357, which is probably the cause why these used to pass on JDK 8. [3] AssertJ Caveat: ******************* Added workaround to an AssertJ issue in Java 8, see: assertj/assertj#1046 [4] Kotlin Caveats: ******************* - Fixed building of Javadoc under JDK9 polluted by Kotlin classes that are deemed invalid by the Java 9 doclet. (these used to be ignored in Java 8) - Dokka is not building, so we exclude kdocZip (and thus dokka) under JDK9 (see Kotlin/dokka#220)
This commit builds under both JDK8 and JDK9 in Travis CI. Minus a couple of caveats, it fixes the JDK9 build with various changes: Version Bumps - Update to Gradle 4.2.1 for full compatibility with JDK9 - Bump asciidoctor plugin^[1] - Bump Mockito^[2] and Jacoco to their latest JDK9-compatible versions - Bump AssertJ to 3.8.0^[3] - Bump Kotlin Gradle Plugin to 1.5.51^[4] [1] Asciidoctor Caveat: *********************** In JDK9, don't build the PDF as no compatible combination of asciidoctorJ-pdf could be found... [2] Tests Adaptation, Mockito Caveats: ************************************** Fix scan tests that use mocks of non-Scannable PARENTs/ACTUALs Added MockUtils with interfaces that help creating Scannable mocks that also implement another interface for combinations not naturally found in production code. See Mockito issue mockito/mockito#357, which is probably the cause why these used to pass on JDK 8. [3] AssertJ Caveat: ******************* Added workaround to an AssertJ issue in Java 8, see: assertj/assertj#1046 [4] Kotlin Caveats: ******************* - Fixed building of Javadoc under JDK9 polluted by Kotlin classes that are deemed invalid by the Java 9 doclet. (these used to be ignored in Java 8) - Dokka is not building, so we exclude kdocZip (and thus dokka) under JDK9 (see Kotlin/dokka#220)
@raphw Yes, the warning would be very helpful. |
There's an Error Prone check that detects this problem at compile-time: http://errorprone.info/bugpattern/MockitoCast. It can also be run as a refactoring to add work-arounds to affected code. |
This is broken from JDK9 on for generic types. See also: mockito/mockito#357
This solves a large number of edge-cases where `null` will actually remove the runtime ClassCastException. This essentially negates the whole MockitoCast ErrorProne check. We can still not support every use case, but causing a NPE instead of a CCE does not seem to make this worse. I am still running internal tests within Google to see if there are any regressions, but I already saw that some of the test failures we had with ByteBuddy were resolved with this particular patch. Note that this now fully closes #357. A previous PR resolved the same issue with ReturnsSmartNulls: #1576. Fixes #357
This solves a large number of edge-cases where `null` will actually remove the runtime ClassCastException. This essentially negates the whole MockitoCast ErrorProne check. We can still not support every use case, but causing a NPE instead of a CCE does not seem to make this worse. I am still running internal tests within Google to see if there are any regressions, but I already saw that some of the test failures we had with ByteBuddy were resolved with this particular patch. Note that this now fully closes #357. A previous PR resolved the same issue with ReturnsSmartNulls: #1576. Fixes #357
This solves a large number of edge-cases where `null` will actually remove the runtime ClassCastException. This essentially negates the whole MockitoCast ErrorProne check. We can still not support every use case, but causing a NPE instead of a CCE does not seem to make this worse. I am still running internal tests within Google to see if there are any regressions, but I already saw that some of the test failures we had with ByteBuddy were resolved with this particular patch. Note that this now fully closes mockito#357. A previous PR resolved the same issue with ReturnsSmartNulls: mockito#1576. Fixes mockito#357
While the generics metadata extractor has been improved, not every possible scenarios are covered even Javac in version 8 do not follow through, in order to avoid a stealth return of the bugs spot in mockito#357 this change improves the guard by making sure extracted generic data does not have extra-interfaces as well.
…port Some of the previously uncommented tests now pass with Java 8 and Java 11. The fixes mostly consist of workarounds around Mockito quirks. Mockitos RETURNS_DEEP_STUBS stubbing mode seems to be broken for methods with generic return types, see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=535853 mockito/mockito#357
…port Some of the previously uncommented tests now pass with Java 8 and Java 11. The fixes mostly consist of workarounds around Mockito quirks. Mockitos RETURNS_DEEP_STUBS stubbing mode seems to be broken for methods with generic return types, see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=535853 mockito/mockito#357
This was a temporary check to support upgrading to the JDK 9 javac. The upstream mockito bug is fixed: mockito/mockito#357 Closes #458 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=312131946
This was a temporary check to support upgrading to the JDK 9 javac. The upstream mockito bug is fixed: mockito/mockito#357 Closes #458 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=312131946
JDK 9 fixes a javac bug (JDK-8058199) that was causing checkcast intructions to be skipped. Previously javac used the parameter types of a method symbol's erased type as targets when translating the arguments. In JDK 9, javac has been fixed to use the inferred types as targets. The fix causes additional checkcasts to be generated if the inferred types do not have the same erasure.
The fix breaks Mockito answer strategies that pick types based on the erased method signature's return type, and causes tests to fail with ClassCastExceptions when compiled with the JDK 9 javac.
Example 1
compiled with javac 8
compiled with javac 9
The erased return type of
Super.g
isObject
, but the expected return type ofSub.g
isBoolean
. If the answer strategy returnsObject
the checkcast fails.Example 2
compiled with javac 8
compiled with javac 9
The erased return type of
Foo.getFirst
isObject
, but the inferred return type ofgetFirst(Iterable<Boolean>)
isBoolean
. If the answer strategy returnsObject
the checkcast fails.The first example could be fixed by using
GenericMetadataSupport
in all of the answer implementations instead ofinvocation.getMethod().getReturnType()
.It gets more difficult if the mock's type is an instantiation of a generic type (e.g.
@Mock Foo<Bar> x;
), since the field's type arguments get dropped. I think fixing that would require adding support for mocking types, not just classes.For the second example, returning the right answer requires considering the generic signature of the invoked method, and performing type inference using the argument types. Unfortunately the runtime type of the argument is going to be a raw
Iterable
and the inference depends on knowing it'sIterable<Boolean>
, so I'm not sure what to do there.The text was updated successfully, but these errors were encountered: