如何使用jMockit模拟本机方法

时间:2009-12-01 19:54:23

标签: java jmockit

我正在尝试使用jMockit来存根调用netscape.javascript.JSObject,遗憾的是这是一个带有一些本地方法的抽象类,这两个方法都不适合jMockit。有没有办法让我用jMockit或者使用普通的java来解决这个问题(如果可能的话我不想引入新的库)?我试图注入模拟的代码看起来如下(不要问):

  

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

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

  

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

从我的研究中我发现它意味着它试图模仿本地方法。

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

2 个答案:

答案 0 :(得分:3)

您使用的是哪个版本的JMockit?根据{{​​3}},您应该能够毫无问题地模拟本机方法。

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

编辑:正如您所指出的,这不适用于Java 1.5。我担心唯一的解决方案是使用装饰器包装您的本机对象,该装饰器只是作为传递操作。这有点令人头疼,但它会允许嘲笑/拦截等。

答案 1 :(得分: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“target”指定为“1.5”即可。在Eclipse中,“Project Properties - &gt; Java Compiler”下有一个“JDK Compliance”配置。

相关问题