IntelliJ IDEA built-in Test Runner conflicts with Mockito when mocking gRPC's StreamObserver interface
- 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
- Create a test class using Mockito that mocks the io.grpc.stub.StreamObserver interface
- Run the test normally - it passes
- Run the test at the file-level with coverage using the IntelliJ IDEA runner – it passes
- 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`
Please sign in to leave a comment.
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.
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!