java - 为什么我不能使用 JMockit 模拟数学

标签 java unit-testing math jmockit

我在使用 JMockit (1.21) 模拟 java.lang.Math 时遇到问题。请参阅下文,了解我的实际类(class)的简化使用。基本上在我的代码中的某个地方我使用 Math.pow(...) 并且我希望模拟它。

public final class Calculator {
    public final double power(double base, double exponent) {
        return Math.pow(base, exponent);
    }
}

对于我的测试代码来说,这个测试是有效的。

@Test
public void simpleTestWithoutMock() {
    Calculator calculator = new Calculator();
    double result = calculator.power(2, 3);
    assertThat(result).isEqualTo(8);
}

此测试失败。

@Test
public void simpleTestWithMock(@Mocked Math math) {
    new Expectations() {{ // This would be line 67 in below stracktrace
        Math.pow(2,3); result = 1;
    }};

    Calculator calculator = new Calculator();
    double result = calculator.power(2, 3);
    assertThat(result).isEqualTo(1);
}

我收到的错误消息:

java.lang.NoClassDefFoundError: nl/endran/sandbox/CalculatorTest$1

        at nl.endran.sandbox.CalculatorTest.simpleTestWithMock(CalculatorTest.java:67)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:483)
        at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
        at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
        at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:483)
        at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
        Caused by: java.lang.ClassNotFoundException: nl.endran.sandbox.CalculatorTest$1
        at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        ... 9 more

我可以像这样模拟其他系统类,例如SystemRunTime,但是Math似乎不起作用(也不就此事而言,是String)。我知道如何规避这是我的测试,所以我没有被阻止或发生任何事情,但我不明白为什么 Math 不能被 mock 。删除 Expectations block 将不再导致 NoClassDefFoundError 错误。我怀疑具有像 public static native 这样的签名的方法会在其中发挥作用,但我找不到任何东西。

最佳答案

因为 1) 来自 java.lang.Math 的方法(特别是 Math.min(a, b))始终被调用 来自 JRE 的其他类(例如,查看 java.lang.String 内部),以及 2) 当 JMockit 模拟一个类时(无论如何,使用 @Mocked) ,它会在测试期间被模拟,无论调用来自何处。

底线是,不要模拟低级 JRE 类,除非您真的知道自己在做什么。在这种特殊情况下,JMockit 可能应该拒​​绝对 java.lang.Math 的完全模拟,因为实际上没有充分的理由(我可以看到)这样做。

关于java - 为什么我不能使用 JMockit 模拟数学,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35561834/

相关文章:

Java:双击 JSlider 重置

unit-testing - 启动 RSpec-puppet 单元测试的正确方法

c# - 如何在单元测试执行中更改方法的返回值

ios - 使用 CMDeviceMotion 时,如果设备竖直向上(pitch = 90),它真的很不稳定。无论如何要解决这个问题?

java - 使用倒计时器功能防止这种情况发生

java - 在intellij idea中使用gradle构建第一个java项目,此构建中使用了已弃用的Gradle功能

java.lang.UnsupportedClassVersionError 即使 java -version 和 javac -version 相同

c# - 我应该在方法没有明显返回的情况下对代码进行单元测试吗?

JavaScript 随机数

algorithm - 使用有限算术运算符集的 Ceil 函数