【问题标题】:Powermockito - cannot mock/spy a system classPowermockito - 不能模拟/监视系统类
【发布时间】:2019-09-10 14:57:34
【问题描述】:

我正在尝试像这样模拟java.nio.file.Files 类中的静态方法:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;

@RunWith(PowerMockRunner.class)
@PrepareForTest({Files.class})
public class MockStaticTest {

    @Test
    public void test() throws IOException {
        Path absolutePath = Paths.get("AB", "CD", "EF");
        mockStatic(Files.class);
        when(Files.createDirectories(absolutePath)).thenReturn(null);
    }
}

当我执行测试类时,我得到了这个异常:

org.mockito.exceptions.base.MockitoException: 
Cannot mock/spy class java.nio.file.Files
Mockito cannot mock/spy because :
 - final class

    at MockStaticTest.test(MockStaticTest.java:22)
    at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68)
    at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:89)
    at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:97)
    at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:87)
    at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:50)
    at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
    at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)


Process finished with exit code -1

但是,如果我尝试模拟任何其他最终类,它可以正常工作,例如:

import io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;

@RunWith(PowerMockRunner.class)
@PrepareForTest({Files.class, NettyChannelBuilder.class})
public class MockStaticTest {

    @Test
    public void test() throws IOException {
        Path absolutePath = Paths.get("AB", "CD", "EF");
//        mockStatic(Files.class);
        mockStatic(NettyChannelBuilder.class);
//        when(Files.createDirectories(absolutePath)).thenReturn(null);
        when(NettyChannelBuilder.forAddress("", 0)).thenReturn(null);
    }
}

有人可以帮我解决这个问题吗?为什么Files 类会抛出模拟异常?

Maven 依赖:

         <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-api-mockito2</artifactId>
            <version>2.0.2</version>
            <scope>test</scope>
          </dependency>

    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-core</artifactId>
      <version>2.28.2</version>
      <scope>test</scope>
    </dependency>

【问题讨论】:

  • 我无法重现该问题。从字面上复制您的示例代码并将其作为 unittest 运行不会给我任何错误。
  • 哇...你复制了具有`when(Files.createDirectories(absolutePath)).thenReturn(null);`的那个。感谢您调查它
  • 检查了别人的机器,他也遇到了同样的错误。
  • 虽然这不能解决您的问题,但请查看 powermock 文档中的 Mocking system classes 部分。这与mockito-core 2.26.0 结合使用。您应该在他们的问题跟踪器中提交错误报告。

标签: java unit-testing mockito powermock powermockito


【解决方案1】:

Mockito 和 PowerMock 版本不匹配。检查Powermock documentation 以了解版本对齐情况。

这是我用来重现问题的 maven 设置(文件刹车,与 NettyChannelBuilder 配合使用):

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>3.0.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-core</artifactId>
        <version>2.0.0</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-module-junit4</artifactId>
        <version>2.0.0</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-api-mockito2</artifactId>
        <version>2.0.0</version>
        <scope>test</scope>
    </dependency>

如果我切换到 Mockito 2.10.0,这两个类都可以工作:

   <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>2.10.0</version>
        <scope>test</scope>
    </dependency>

【讨论】:

  • 那么它是否适用于其他静态类?我尝试使用 PowerMock 模拟其他最终类和最终静态方法,这些方法没有任何问题。我正面临这个特定课程的问题。但我感谢您的评论,并会尽快更新版本
  • 这看起来确实很奇怪,但它确实是这样工作的。我将使用我用来复制它的 maven 版本和正在运行的版本更新答案,也许它会对你有所帮助。
  • 它仍在使用低于2.27.0mockito 版本。请注意,powermock 2.0.2 是针对 2.23.0 构建的,之后有些东西显然坏了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-22
  • 1970-01-01
  • 2012-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多