为什么我不能使用JMockit模拟数学 [英] Why can't I mock Math using JMockit

查看:114
本文介绍了为什么我不能使用JMockit模拟数学的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用JMockit(1.21)模拟出java.lang.Math时遇到问题.请参阅以下内容,以简化我的实际课程.基本上在我的代码中的某个地方,我使用Math.pow(...)并希望对其进行模拟.

I am running into a problem mocking out java.lang.Math using JMockit (1.21). See below for a simplified use of my actual class. Basically somewhere in my code I use Math.pow(...) and I whish to mock it.

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

对于我的测试代码,此测试有效.

As for my test code, this test works.

@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这样的签名的方法在其中起作用,但是我找不到任何东西.

I am able to mock other system classes like System and RunTime like this, but Math just doesn't seem to work (nor does String for that matter). I know how to circumvent this is my tests, so I am not blocked or anything, but I cannot understand why Math cannot be mocked. Removing the Expectations block will not cause the NoClassDefFoundError error anymore. I suspect methods that have a signature like public static native to play a role in this, but I cannot find anything.

推荐答案

因为1)java.lang.Math(尤其是Math.min(a, b))中的方法始终被其他类从调用 JRE(例如,在java.lang.String中查看)和2),当JMockit模拟一个类(无论如何使用@Mocked)时,在测试期间都会对其进行模拟,而与 where 无关.来电来了.

Because 1) methods from java.lang.Math (in particular, Math.min(a, b)) get called all the time by other classes from the JRE (for example, look inside java.lang.String), and 2) when JMockit mocks a class (with @Mocked, anyway), it gets mocked for the duration of the test, regardless of where the calls are coming from.

最重要的是,除非您真的知道自己在做什么,否则请不要嘲笑低级JRE类.在这种特殊情况下,JMockit可能会拒绝java.lang.Math的完整模拟,因为确实没有充分的理由(我可以看到).

Bottom line, don't mock low-level JRE classes unless you really know what you are doing. In this particular case, JMockit should probably deny the full mocking of java.lang.Math, as really there is no good reason (that I can see) for doing it.

这篇关于为什么我不能使用JMockit模拟数学的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆