为什么我不能使用JMockit模拟Math

时间:2016-02-22 19:08:41

标签: java unit-testing math jmockit

我遇到了使用JMockit(1.21)模拟java.lang.Math的问题。请参阅下面的实际课程的简化用法。基本上在我的代码的某处,我使用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不能被嘲笑。删除Expectations块不会再导致NoClassDefFoundError错误。我怀疑有public static native这样的签名的方法在这方面起作用,但我找不到任何东西。

1 个答案:

答案 0 :(得分:1)

因为1)来自java.lang.Math的方法(特别是Math.min(a, b))被JRE中的其他类一直调用(例如,查看{{1} 2)当JMockit模拟一个类(无论如何都使用java.lang.String)时,它会在测试期间被模拟,无论哪里调用来自。< / p>

最重要的是,除非你真的知道自己在做什么,否则不要嘲笑低级别的JRE课程。在这种特殊情况下,JMockit应该否认@Mocked的完全嘲弄,因为实际上没有充分的理由(我可以看到)。