2

我正在尝试使用 jMockit 来存根对 netscape.javascript.JSObject 的调用,不幸的是,这是一个包含一些本机方法的抽象类,这两种方法都不能很好地与 jMockit 配合使用。我有什么办法可以用 jMockit 或纯 java 来解决这个问题(如果可能的话,我宁愿不必引入新的库)?我试图注入模拟的代码如下所示(不要问):

JSObject win = JSObject.getWindow(this);
String someVal = (String) win.call("foo", new String[] {""});

不幸的是,我无法修改有问题的代码(再一次,不要问),所以我可以对其进行任何类型的单元测试的唯一方法是,如果我能弄清楚如何存根或以其他方式消除对JS对象。我当前的模拟实现为调用getWindow返回一个自身的新实例,并为调用返回一个常量字符串,但当然它在运行时失败并抱怨

类重新定义失败:试图更改方法修饰符

从我的研究中我发现这意味着它正在尝试模拟本机方法。

编辑:由于目标平台,我需要使用 JDK 1.5 来构建/测试,因此任何解决方案都必须在 1.5 上可行。

4

2 回答 2

3

您使用的是哪个版本的 JMockit?据此,您应该能够毫无问题地模拟本机方法

@Test
public void mockNativeMethod() {
    new MockUp<Runtime>() {
        @Mock
        @SuppressWarnings("unused")
        int availableProcessors() {
            return 999;
        }
    };
    assertEquals(999, Runtime.getRuntime().availableProcessors());
}

编辑:正如您所指出的,这不适用于 Java 1.5。我担心唯一的解决方案是用一个简单地作为传递操作的装饰器来包装你的原生对象。这有点让人头疼,但它允许模拟/拦截等。

于 2009-12-01T20:05:47.417 回答
1

正如 Brian 指出的那样,JMockit 支持模拟本地方法。(下面的测试中显示的 Expectations API 也支持它。)

@Test // this only works under JDK 1.6+; JDK 1.5 does not support redefining natives
public void mockNativeMethod()
{
   new Expectations()
   {
      final System system = null;

      {
         System.nanoTime(); returns(0L);
      }
   };

   assertEquals(0, System.nanoTime());
}

不过,问题在于 JDK 1.5 中的 JVMTI 实现还不是很成熟,不支持重新定义native方法。

我了解您需要在 JDK 1.5 环境中部署生产代码,但这不应该成为在您的开发环境中使用 JDK 1.6 的障碍。通常,在 JDK 1.6 上运行测试,甚至使用 JDK 1.6 编译器编译所有源代码应该是完全安全和容易的。您只需将 javac“目标”指定为“1.5”。在 Eclipse 中,“Project Properties -> Java Compiler”下有一个“JDK Compliance”配置。

于 2009-12-05T01:23:24.000 回答