IntelliJ IDEA built-in Test Runner conflicts with Mockito when mocking gRPC's StreamObserver interface

Answered

- Bug description: IntelliJ IDEA's built-in code coverage runner conflicts with Mockito when mocking gRPC's StreamObserver interface, causing tests to fail only during coverage runs. Specifically, this  only happens when you run all tests in a package with code coverage, not when you run a single file with code coverage.
 

- Environment details:
   - Java version: 21
   - JVM vendor: Ubuntu
   - JVM version: 21.0.5+11-Ubuntu-1ubuntu122.04
   - OS: Linux (WSL2)
   - IntelliJ IDEA version: 2024.3.5 Ultimate Edition
 

- Workaround found: Switching to JaCoCo coverage runner resolves the issue
 

Steps to Reproduce

  1. Create a test class using Mockito that mocks the io.grpc.stub.StreamObserver interface
  2. Run the test normally - it passes
  3. Run the test at the file-level with coverage using the IntelliJ IDEA runner – it passes
  4. Run all tests at the package-level with coverage using the Intellij IDEA runner – it fails

Additional Context
This appears to be a conflict between the IntelliJ code coverage instrumentation and Mockito's inline mocking mechanism.

 

Specifically the StreamObserver I'm referring to is io.grpc.stub.StreamObserver

 

Example of the underlying exception:

org.mockito.exceptions.base.MockitoException: Could not modify all classes [interface io.grpc.stub.StreamObserver]

at org.mockito.junit.jupiter.MockitoExtension.beforeEach(MockitoExtension.java:160)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
Suppressed: java.lang.NullPointerException: Cannot invoke "java.util.Set.forEach(java.util.function.Consumer)" because the return value of "org.junit.jupiter.api.extension.ExtensionContext$Store.remove(Object, java.lang.Class)" is null
at org.mockito.junit.jupiter.MockitoExtension.afterEach(MockitoExtension.java:194)
... 2 more
Caused by: org.mockito.exceptions.base.MockitoException: Could not modify all classes [interface io.grpc.stub.StreamObserver]
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)
... 3 more
Caused by: java.lang.UnsupportedOperationException: class redefinition failed: attempted to delete a method
at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:225)
at org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator.triggerRetransformation(InlineBytecodeGenerator.java:285)
at org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator.mockClass(InlineBytecodeGenerator.java:218)
at org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator.lambda$mockClass$0(TypeCachingBytecodeGenerator.java:78)
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:75)
at org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker.createMockType(InlineDelegateByteBuddyMockMaker.java:406)
at org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker.doCreateMock(InlineDelegateByteBuddyMockMaker.java:365)
at org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker.createMock(InlineDelegateByteBuddyMockMaker.java:344)
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:84)
at org.mockito.Mockito.mock(Mockito.java:2185)
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:62)
at org.mockito.internal.configuration.InjectingAnnotationEngine.process(InjectingAnnotationEngine.java:47)
at org.mockito.MockitoAnnotations.openMocks(MockitoAnnotations.java:81)
at org.mockito.internal.framework.DefaultMockitoSession.<init>(DefaultMockitoSession.java:43)
at org.mockito.internal.session.DefaultMockitoSessionBuilder.startMocking(DefaultMockitoSessionBuilder.java:83)
... 3 more`
0
2 comments
Hello - thanks for the report. I submitted it to YouTrack as https://youtrack.jetbrains.com/issue/IDEA-370334 so that our Java developers can take a look. 

It would help if you could also provide the entire idea.log file: Help | Show Log in... We will check the general flow of events and your other system environment settings.

File can be uploaded securely to our server at https://uploads.jetbrains.com. Make sure to share the id of the upload here so that I can find it.
0

Hi Eric,

If you still have this issue in the latest versions of the IDE, it would be great if you could provide a small test project where it is reproducible for you. We can't seem to reproduce it on our side using simple projects and your instructions.

Thanks!

0

Please sign in to leave a comment.