我在使用 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
我可以像这样模拟其他系统类,例如System
和RunTime
,但是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/