简体   繁体   中英

Mock static method in JUnit 5 using Mockito

I am trying to mock static classes(org.apache.commons.beanutils.Beanutils) for Junit 5 test cases. I came across mockito-inline dependency helps with mocking static classes. I tried to use the mockito-inline in the project for some strange reason it give me compilation error in the absence of mockito-core library.

With mockito-core am getting below:

org.mockito.exceptions.base.MockitoException: 
The used MockMaker PowerMockMaker does not support the creation of static mocks

Mockito's inline mock maker supports static mocks based on the Instrumentation API.
You can simply enable this mock mode, by placing the 'mockito-inline' artifact where you are currently using 'mockito-core'.
Note that Mockito's inline mock maker is not supported on Android.
    at com.xx.xx.xx.AvroCopyPropertiesInvocationTargetExceptionScenario(CreditOfferServiceTest.java:1197)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:675)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:125)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:132)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:124)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:74)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:104)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:62)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:43)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:35)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:202)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:198)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:69)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229)
    at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197)
    at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:137)
    at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:98)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:542)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:770)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)

Without the core - compilation issue. Please find the test dependency breakdown without mockito-core :

[INFO] +- org.powermock:powermock-api-mockito2:jar:2.0.9:test
[INFO] |  \- org.powermock:powermock-api-support:jar:2.0.9:test
[INFO] |     +- org.powermock:powermock-reflect:jar:2.0.9:test
[INFO] |     \- org.powermock:powermock-core:jar:2.0.9:test
[INFO] +- org.mockito:mockito-inline:jar:3.6.28:test
[INFO] |  \- org.mockito:mockito-core:jar:3.1.0:test
[INFO] |     +- net.bytebuddy:byte-buddy:jar:1.10.10:test
[INFO] |     +- net.bytebuddy:byte-buddy-agent:jar:1.10.10:test
[INFO] |     \- org.objenesis:objenesis:jar:2.6:test
[INFO] +- org.mockito:mockito-junit-jupiter:jar:3.6.0:test
[INFO] |  \- org.junit.jupiter:junit-jupiter-api:jar:5.5.2:test
[INFO] |     +- org.opentest4j:opentest4j:jar:1.2.0:test
[INFO] |     \- org.junit.platform:junit-platform-commons:jar:1.5.2

You need to use mockito-inline version 3.4.0 or higher and remove mockito-core from your dependencies ( mockito-inline depends on mockito-core so it will be retrieved automatically).

That way, you will be using mockito static mocking correctly, but it wouldn't solve the exception that you posted.

To fix it, you need to remove all dependencies of powermock as it conflicts with mockito and causes this error

The used MockMaker PowerMockMaker does not support the creation of static mocks

You have to add /mockito-extensions/org.mockito.plugins.MockMaker file to the class path containing the value mock-maker-inline . Easiest way to do that is put it in the src/test/resources directory.

For more details check the Mockito documentation.

https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#Mocking_Final

In my case we were using spring boot and below dependency for spring-boot-starter-test and mockito-core was coming internally with spring-boot-starter-test

testImplementation 'org.springframework.boot:spring-boot-starter-test'

use gradle dependencies to find this

+--- org.springframework.boot:spring-boot-starter-test -> 2.6.6
|    +--- org.springframework.boot:spring-boot-starter:2.6.6 (*)
|    +--- org.springframework.boot:spring-boot-test:2.6.6
|    |    \--- org.springframework.boot:spring-boot:2.6.6 (*)
|    +--- org.springframework.boot:spring-boot-test-autoconfigure:2.6.6
|    |    +--- org.springframework.boot:spring-boot:2.6.6 (*)
|    |    +--- org.springframework.boot:spring-boot-test:2.6.6 (*)
|    |    \--- org.springframework.boot:spring-boot-autoconfigure:2.6.6 (*)
|    +--- com.jayway.jsonpath:json-path:2.6.0
|    |    +--- net.minidev:json-smart:2.4.7 -> 2.4.8
|    |    |    \--- net.minidev:accessors-smart:2.4.8
|    |    |         \--- org.ow2.asm:asm:9.1 -> 9.3
|    |    \--- org.slf4j:slf4j-api:1.7.30 -> 1.7.36
|    +--- jakarta.xml.bind:jakarta.xml.bind-api:2.3.3
|    |    \--- jakarta.activation:jakarta.activation-api:1.2.2
|    +--- org.assertj:assertj-core:3.21.0
|    +--- org.hamcrest:hamcrest:2.2
|    +--- org.junit.jupiter:junit-jupiter:5.8.2
|    |    +--- org.junit:junit-bom:5.8.2
|    |    |    +--- org.junit.jupiter:junit-jupiter:5.8.2 (c)
|    |    |    +--- org.junit.jupiter:junit-jupiter-api:5.8.2 (c)
|    |    |    +--- org.junit.jupiter:junit-jupiter-params:5.8.2 (c)
|    |    |    \--- org.junit.platform:junit-platform-commons:1.8.2 (c)
|    |    +--- org.junit.jupiter:junit-jupiter-api:5.8.2
|    |    |    +--- org.junit:junit-bom:5.8.2 (*)
|    |    |    +--- org.opentest4j:opentest4j:1.2.0
|    |    |    +--- org.junit.platform:junit-platform-commons:1.8.2
|    |    |    |    +--- org.junit:junit-bom:5.8.2 (*)
|    |    |    |    \--- org.apiguardian:apiguardian-api:1.1.2
|    |    |    \--- org.apiguardian:apiguardian-api:1.1.2
|    |    \--- org.junit.jupiter:junit-jupiter-params:5.8.2
|    |         +--- org.junit:junit-bom:5.8.2 (*)
|    |         +--- org.junit.jupiter:junit-jupiter-api:5.8.2 (*)
|    |         \--- org.apiguardian:apiguardian-api:1.1.2
|    +--- org.mockito:mockito-core:4.0.0
|    |    +--- net.bytebuddy:byte-buddy:1.11.19 -> 1.11.22
|    |    \--- net.bytebuddy:byte-buddy-agent:1.11.19 -> 1.11.22
|    +--- org.mockito:mockito-junit-jupiter:4.0.0
|    |    \--- org.mockito:mockito-core:4.0.0 (*)

So, 2 steps to solve this issue.

Exclude the mockito-core from spring-boot-starter-test

testImplementation ('org.springframework.boot:spring-boot-starter-test') 
 {
   exclude group: 'org.mockito', module :'mockito-core'
 }

And now include the mockito-inline

testImplementation 'org.mockito:mockito-inline:4.6.1'

This will solve the issue.

Add the following per https://www.baeldung.com/mockito-mock-static-methods :

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-inline</artifactId>
    <version>3.8.0</version>
    <scope>test</scope>
</dependency>

I have some resolutions steps for same.

Please replace you dependency with below.

 <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-inline</artifactId> <version>4.5.1</version> <scope>test</scope> </dependency>

if use 4.5.1 or latest your code will work

Also use your try with resource to mock static method

try (MockedStatic<WelcomeUtil> theMock = Mockito.mockStatic(WelcomeUtil.class)) {
            theMock.when(() -> WelcomeUtil.generateWelcome("John"))
                   .thenReturn("Guten Tag John");

            assertEquals("Guten Tag John", WelcomeUtil.generateWelcome("John"));
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM