使用 Mockito 在 JUnit 5 中模拟静态方法

Aru*_*ian 30 java junit mockito powermock mockstatic

我正在尝试为 Junit 5 测试用例模拟静态类(org.apache.commons.beanutils.Beanutils)。我发现mockito-inline依赖有助于模拟静态类。我尝试在项目中使用 ,mockito-inline由于一些奇怪的原因,它在没有库的情况下给我编译错误mockito-core

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)
Run Code Online (Sandbox Code Playgroud)

没有核心-编译问题。请查找不带以下内容的测试依赖项细分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

Run Code Online (Sandbox Code Playgroud)

Amg*_*afy 23

您需要使用mockito-inline版本3.4.0或更高版本并mockito-core从依赖项中删除(mockito-inline取决于mockito-core因此它将自动检索)。

这样,您将正确使用mockito静态模拟,但它不会解决您发布的异常。

要修复它,您需要删除所有依赖项,powermock因为它与 发生冲突mockito并导致此错误

The used MockMaker PowerMockMaker does not support the creation of static mocks
Run Code Online (Sandbox Code Playgroud)


San*_*ani 14

就我而言,我们使用的是 spring boot 以及 spring-boot-starter-test 的以下依赖项,而mockito-core 是在 spring-boot-starter-test 内部提供的

testImplementation 'org.springframework.boot:spring-boot-starter-test'
Run Code Online (Sandbox Code Playgroud)

使用 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 (*)
Run Code Online (Sandbox Code Playgroud)

因此,解决这个问题有两个步骤。

从 spring-boot-starter-test 中排除mockito-core

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

现在包括mockito-inline

testImplementation 'org.mockito:mockito-inline:4.6.1'
Run Code Online (Sandbox Code Playgroud)

这将解决这个问题。

  • 以下文章分享了对我有帮助的替代方案:https://www.baeldung.com/mockito-mock-static-methods#configuring-mockito-for-static-methods。这允许我配置现有的 mockito 扩展以允许内联模拟 (2认同)

Sma*_*der 12

根据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>
Run Code Online (Sandbox Code Playgroud)


Era*_*nda 9

您必须将/mockito-extensions/org.mockito.plugins.MockMaker文件添加到包含值mock-maker-inline的类路径中。最简单的方法是将其放在 src/test/resources 目录中。

有关更多详细信息,请查看 Mockito 文档。

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


小智 6

我有一些相同的解决步骤。

请将您的依赖项替换为以下内容。

<dependency>
                <groupId>org.mockito</groupId>
                <artifactId>mockito-inline</artifactId>
                <version>4.5.1</version>
                <scope>test</scope>
            </dependency>
Run Code Online (Sandbox Code Playgroud)

如果使用 4.5.1 或最新版本,您的代码将可以工作

还可以使用您的 try 和资源来模拟静态方法

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

            assertEquals("Guten Tag John", WelcomeUtil.generateWelcome("John"));
        }
Run Code Online (Sandbox Code Playgroud)