DEV Community

loading...
Cover image for How to Fix A "Mockito cannot mock this class" Exception in A Spring Boot App

How to Fix A "Mockito cannot mock this class" Exception in A Spring Boot App

scottshipp profile image scottshipp ・3 min read

Recently I started a new Spring Boot app using version 2.0.5 and I used Java 11. Everything seemed like no big deal at first and I got through some of the bootstrapping phases of getting a walking skeleton going, building the Docker container with Maven, and even pushing the snapshot version and its Docker container out to AWS ECR.

Then I wrote the first controller, and, unexpectedly, I couldn’t write an integration test (@WebMvcTest) for it. When I tried, I got the following error:

[ERROR] testGetGear(org.gearbuddy.GearControllerTest)  Time elapsed: 0 s  < << ERROR!
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.mockito.exceptions.base.MockitoException: 

Mockito cannot mock this class: interface org.gearbuddy.data.GearRepository.

Mockito can only mock non-private & non-final classes.
If you're not sure why you're getting this error, please report to the mailing list.


Java               : 11
JVM vendor name    : Oracle Corporation
JVM vendor version : 11.0.2+9-Ubuntu-3ubuntu118.04.3
JVM name           : OpenJDK 64-Bit Server VM
JVM version        : 11.0.2+9-Ubuntu-3ubuntu118.04.3
JVM info           : mixed mode, sharing
OS name            : Linux
OS version         : 4.15.0-48-generic


Underlying exception : java.lang.UnsupportedOperationException: Cannot define class using reflection
Caused by: java.lang.UnsupportedOperationException: Cannot define class using reflection
Caused by: java.lang.IllegalStateException: Could not find sun.misc.Unsafe
Caused by: java.lang.NoSuchMethodException: sun.misc.Unsafe.defineClass(java.lang.String, [B, int, int, java.lang.ClassLoader, java.security.ProtectionDomain)

Huh, that's weird!

This was the code it couldn't mock:

public interface GearRepository extends CrudRepository {
}

Literally nothing special!

How did I fix it?

Tools lying on a workbench

The Solution

The solution was just to explicitly add a newer version of Mockito to my POM:

<!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>2.22.0</version>
    <scope>test</scope>
</dependency>

Before this, I had Mockito 2.15.0, which came in as a transitive dependency through spring-boot-starter-test.

So why does adding the explicit Mockito version work?

Well, the problem is that MockBean in the version of Mockito imported as a transitive dependency (I think from Spring Boot parent pom (?) but I didn't check) used stuff from the sun.misc.unsafe package. Which was removed in Java 9.

The unfortunate thing was that it took me hours to figure out that's what was going on. Because if you start googling around for "Mockito cannot mock this class CrudRepository" you'll hit a lot of articles about how Spring Boot (particularly in regards to the @WebMvcTest annotation) creates the application context and when beans are available and what name they have when they're made available and all that.

On the other hand, if you look up something like "Mockito java 11 sun.misc.unsafe" (which you'll eventually try once you read all the way through to the end of the above stack trace) you'll come across this very helpful Stack Overflow answer.

The new faster upgrade cycle for Java is likely to introduce some dependency issues like this one to your applications. Thankfully the Java community online is a strong and helpful one. With a little careful reading of any error output, you will have no problems finding the solutions you need.

Discussion

pic
Editor guide
Collapse
rovamad profile image
Marcos Rojas

Thanks, this post help me

Collapse
mirrane0 profile image
mirrane0

thanks, i was trying to fix it for 2 hours.

Collapse
ramakria123 profile image
rama anne

Hi
Thanks for the post adding mockito the test project pom.xml fixed it
rama anne