Skip to content
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

Mockito "cannot mock" exceptions with IBM Semeru Java 11 and 17 #2995

Open
yogregg opened this issue May 1, 2023 · 5 comments
Open

Mockito "cannot mock" exceptions with IBM Semeru Java 11 and 17 #2995

yogregg opened this issue May 1, 2023 · 5 comments

Comments

@yogregg
Copy link

yogregg commented May 1, 2023

Hi,

I'm having a problem with Mockito running under IBM Semeru Java 11 and 17 that I'm not having with Oracle versions. I'm using Mockito 5.3.1 and byte-buddy 1.14.4, but also have this problem with Mockito 5.2.0 and byte-buddy 1.14.3. The Java details in the error message below are from Windows Semeru Java 11 but I also get this on Linux, and also on even the latest Semeru Java 17. The problem is that in some cases I'm getting a "Mockito cannot mock this class" MockitoException. I give one such example below that complains about not being able to mock java.io.InputStream, but I'm also getting this on some of my company's own classes and on proprietary third party classes that we use. Much of our mocking code runs fine, but in the places where this fails, it fails consistently in this way.

Here's an example exception:

[ERROR] injectMocks(com.company.commons.utils.backup.core.ByteBufferBasedDatabaseDataInputStreamTest)  Time elapsed: 2.157 s  <<< FAILURE!
org.mockito.exceptions.base.MockitoException:

Mockito cannot mock this class: class java.io.InputStream.

If you're not sure why you're getting this error, please open an issue on GitHub.


Java               : 11
JVM vendor name    : Eclipse OpenJ9
JVM vendor version : openj9-0.35.0
JVM name           : Eclipse OpenJ9 VM
JVM version        : 11.0.17+8
JVM info           : JRE 11 Windows 10 amd64-64-Bit Compressed References 20221031_487 (JIT enabled, AOT enabled)
OpenJ9   - e04a7f6c1
OMR      - 85a21674f
JCL      - a94c231303 based on jdk-11.0.17+8
OS name            : Windows 10
OS version         : 10.0


You are seeing this disclaimer because Mockito is configured to create inlined mocks.
You can learn about inline mocks and their limitations under item #39 of the Mockito class javadoc.

Underlying exception : org.mockito.exceptions.base.MockitoException: Could not modify all classes [class java.io.InputStream, interface java.io.Closeable, class java.lang.Object, interface java.lang.AutoCloseable]
        at com.company.commons.utils.backup.core.ByteBufferBasedDatabaseDataInputStreamTest.injectMocks(ByteBufferBasedDatabaseDataInputStreamTest.java:51)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:124)
        at org.testng.internal.MethodInvocationHelper.invokeMethodConsideringTimeout(MethodInvocationHelper.java:59)
        at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:458)
        at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:222)
        at org.testng.internal.Invoker.invokeMethod(Invoker.java:523)
        at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:719)
        at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:989)
        at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
        at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109)
        at org.testng.TestRunner.privateRun(TestRunner.java:648)
        at org.testng.TestRunner.run(TestRunner.java:505)
        at org.testng.SuiteRunner.runTest(SuiteRunner.java:455)
        at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:450)
        at org.testng.SuiteRunner.privateRun(SuiteRunner.java:415)
        at org.testng.SuiteRunner.run(SuiteRunner.java:364)
        at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
        at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:84)
        at org.testng.TestNG.runSuitesSequentially(TestNG.java:1208)
        at org.testng.TestNG.runSuitesLocally(TestNG.java:1137)
        at org.testng.TestNG.runSuites(TestNG.java:1049)
        at org.testng.TestNG.run(TestNG.java:1017)
        at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:135)
        at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.executeSingleClass(TestNGDirectoryTestSuite.java:112)
        at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:99)
        at org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:146)
        at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:379)
        at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:340)
        at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:125)
        at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:413)
Caused by: org.mockito.exceptions.base.MockitoException: Could not modify all classes [class java.io.InputStream, interface java.io.Closeable, class java.lang.Object, interface java.lang.AutoCloseable]
        at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:168)
        at net.bytebuddy.TypeCache$WithInlineExpunction.findOrInsert(TypeCache.java:399)
        at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:190)
        at net.bytebuddy.TypeCache$WithInlineExpunction.findOrInsert(TypeCache.java:410)
        ... 34 more
Caused by: java.lang.instrument.UnmodifiableClassException
        at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
        at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:167)
        at org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator.triggerRetransformation(InlineBytecodeGenerator.java:281)
        at org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator.mockClass(InlineBytecodeGenerator.java:218)
        at org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator.lambda$mockClass$0(TypeCachingBytecodeGenerator.java:47)
        at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:168)
        at net.bytebuddy.TypeCache$WithInlineExpunction.findOrInsert(TypeCache.java:399)
        at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:190)
        at net.bytebuddy.TypeCache$WithInlineExpunction.findOrInsert(TypeCache.java:410)
        at org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator.mockClass(TypeCachingBytecodeGenerator.java:40)
        at org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker.createMockType(InlineDelegateByteBuddyMockMaker.java:396)
        at org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker.doCreateMock(InlineDelegateByteBuddyMockMaker.java:355)
        at org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker.createMock(InlineDelegateByteBuddyMockMaker.java:334)
        at org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker.createMock(InlineByteBuddyMockMaker.java:56)
        at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:99)
        at org.mockito.internal.MockitoCore.mock(MockitoCore.java:88)
        at org.mockito.Mockito.mock(Mockito.java:2101)
        at org.mockito.internal.configuration.MockAnnotationProcessor.processAnnotationForMock(MockAnnotationProcessor.java:79)
        at org.mockito.internal.configuration.MockAnnotationProcessor.process(MockAnnotationProcessor.java:28)
        at org.mockito.internal.configuration.MockAnnotationProcessor.process(MockAnnotationProcessor.java:25)
        at org.mockito.internal.configuration.IndependentAnnotationEngine.createMockFor(IndependentAnnotationEngine.java:44)
        at org.mockito.internal.configuration.IndependentAnnotationEngine.process(IndependentAnnotationEngine.java:72)
        at org.mockito.internal.configuration.InjectingAnnotationEngine.processIndependentAnnotations(InjectingAnnotationEngine.java:73)
        at org.mockito.internal.configuration.InjectingAnnotationEngine.process(InjectingAnnotationEngine.java:47)
        at org.mockito.MockitoAnnotations.openMocks(MockitoAnnotations.java:81)
        ... 34 more

Here's the ByteBufferBasedDatabaseDataInputStreamTest.injectMocks method that this is being thrown from:

  @BeforeMethod(alwaysRun=true)
  public void injectMocks() throws Exception
  {
    MockitoAnnotations.openMocks(this);
    final Mutable<Integer> n = new Mutable(0);
    doAnswer(new Answer()
    {
      @Override
      public Object answer(final InvocationOnMock invocationOnMock) throws Throwable
      {
        byte[] array = (byte[]) invocationOnMock.getArguments()[0];
        int off = (Integer) invocationOnMock.getArguments()[1];
        if (n.getValue() == 0)
        {
          array[off] = (byte) 0xDB;
          array[off + 1] = (byte) 0xC0;
          n.setValue(1);
          return 2;
        }
        else
        {
          array[off] = (byte) 0xDC;
          array[off + 1] = (byte) 0xBE;
          array[off + 2] = (byte) 0x0;
          array[off + 3] = (byte) 0x30;
          return 4;
        }
      }
    }).when(inputStream).read(any(byte[].class), anyInt(), anyInt() );
  }

Has mockito been tested with IBM Semeru Java? Do you have any ideas why this might be happening?

Thanks,
Gregg

@yogregg yogregg changed the title Mockito cannot mock exceptions with IBM Semeru Java 11 and 17 Mockito "cannot mock" exceptions with IBM Semeru Java 11 and 17 May 1, 2023
@TimvdLippe
Copy link
Contributor

Unfortunately, InputStream is one of the classes that Mockito relies on internally for its behavior. Stubbing InputStream will therefore lead to undefined behavior. Additionally, it is advised not to mock classes you don't own: https://github.com/mockito/mockito/wiki/How-to-write-good-tests#dont-mock-a-type-you-dont-own We are working on improving the user experience by working on a DoNotMock feature to avoid mocking classes/methods that are known to crash Mockito internals (#1833). Therefore, I am closing this as "Infeasible". Apologies for the uninformative exception that is thrown.

@yogregg
Copy link
Author

yogregg commented May 8, 2023

@TimvdLippe The problems I was having weren't limited to InputStream or even third party classes. Moreover, all of those tests that are failing for me with IBM Semeru Java are passing with Oracle Java, so the issues aren't inherent to mockito. To see if I could make this clearer, I tried running mockito's own test suite today with IBM Semeru Java (jdk-11.0.17+8) by setting "executable" in mockito's top-level build.gradle, like this:

    tasks.withType(Test) {
        executable = new File("c:/apps/jdk-11.0.17+8-semeru", "bin/java.exe")
    }

The result was that mockito's own tests have about 500 failures in the top-level project alone, and I also noticed failures in subprojects. I didn't look at every single failure, but from a sampling it is nearly all the very same "cannot mock" exceptions that I gave an example of in my original problem report. I've attached the contents of mockito's top level build/reports/tests/test directory for your convenience.

I hope that you will agree that there's a very widespread problem with mockito running under IBM Semeru Java and that this issue deserves to be reopened. The above results came from the Semeru version cited above, but in my testing it doesn't really matter, I've tried various Semeru Java 11 and 17 versions with the same results. Semeru downloads are available at https://developer.ibm.com/languages/java/semeru-runtimes/downloads/

test.zip

@CristhianUlloa
Copy link

@TimvdLippe , any update on this? I am hitting the same issue. But I am only mocking my own classes, so definitely not something Mockito would be dependent on.

@TimvdLippe
Copy link
Contributor

If anybody from IBM or another contributor wants to send us patches on how to fix Mockito on their SDK, we would welcome them.

@bmarwell
Copy link

Duplicate of #2278 (please close this in favour of #2278).
Upstream issue: eclipse-openj9/openj9#17454

Thanks to @paulcheeseman from IBM for providing the link to the upstream issue (I am merely another user, but my company has IBM support and we ran into this, too. So I opened an issue so IBM could work on this more quickly).

Should be fixed by the next OpenJ9 release.

HTH

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants