简体   繁体   English

使用 Mockito 在 JUnit 5 中模拟 static 方法

[英]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.我正在尝试为 Junit 5 个测试用例模拟 static 类(org.apache.commons.beanutils.Beanutils)。 I came across mockito-inline dependency helps with mocking static classes.我遇到了mockito-inline依赖有助于 mocking static 类。 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.我尝试在项目中使用mockito-inline出于某种奇怪的原因,它在没有mockito-core库的情况下给了我编译错误。

With mockito-core am getting below:随着mockito-core越来越低:

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 :请找到没有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).您需要使用mockito-inline版本3.4.0或更高版本,并从您的依赖项中删除mockito-coremockito-inline依赖于mockito-core ,因此它将被自动检索)。

That way, you will be using mockito static mocking correctly, but it wouldn't solve the exception that you posted.这样,您将正确使用 mockito static mocking,但它不会解决您发布的异常。

To fix it, you need to remove all dependencies of powermock as it conflicts with mockito and causes this error要修复它,您需要删除powermock的所有依赖项,因为它与mockito冲突并导致此错误

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 .您必须将/mockito-extensions/org.mockito.plugins.MockMaker文件添加到包含值mock-maker-inline的 class 路径。 Easiest way to do that is put it in the src/test/resources directory.最简单的方法是将它放在 src/test/resources 目录中。

For more details check the Mockito documentation.有关更多详细信息,请查看 Mockito 文档。

https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#Mocking_Final 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在我的情况下,我们使用 spring 启动和以下依赖项用于 spring-boot-starter-test 和 mockito-core 在内部使用 spring-boot-starter-test

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

use gradle dependencies to find this使用 gradle 依赖项找到这个

+--- 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.所以,2个步骤来解决这个问题。

Exclude the mockito-core from spring-boot-starter-test从 spring-boot-starter-test 中排除 mockito-core

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

And now include the mockito-inline现在包括 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 :根据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如果使用 4.5.1 或最新版本,您的代码将有效

Also use your try with resource to mock static method还可以使用您的资源尝试来模拟 static 方法

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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