【问题标题】:Mockito - mocking classes with native methodsMockito - 使用本机方法模拟类
【发布时间】:2012-04-19 07:45:15
【问题描述】:

我有简单的测试用例:

@Test
public void test() throws Exception{
       TableElement table = mock(TableElement.class);
       table.insertRow(0);
}

其中 TableElement 是 GWT 类,其方法 insertRow 定义为:

public final native TableRowElement insertRow(int index);

当我启动测试时,我得到:

java.lang.UnsatisfiedLinkError: com.google.gwt.dom.client.TableElement.insertRow(I)Lcom/google/gwt/dom/client/TableRowElement;
    at com.google.gwt.dom.client.TableElement.insertRow(Native Method)

我认为这与本机的 insertRow 方法有关。是否有任何方法或解决方法可以使用 Mockito 模拟此类方法?

【问题讨论】:

    标签: java gwt mockito native-methods


    【解决方案1】:

    Mockito 本身似乎无法根据这个Google Group thread 模拟本机方法。但是,您确实有两种选择:

    1. TableElement 类包装在一个接口中并模拟该接口以正确测试您的SUT 是否调用了包装的insertRow(...) 方法。缺点是您需要添加额外的接口(当 GWT 项目应该在他们自己的 API 中完成此操作时)以及使用它的开销。接口代码和具体实现如下所示:

      // the mockable interface
      public interface ITableElementWrapper {
          public void insertRow(int index);
      }
      
      // the concrete implementation that you'll be using
      public class TableElementWrapper implements ITableElementWrapper {
          TableElement wrapped;
      
          public TableElementWrapper(TableElement te) {
              this.wrapped = te;
          }
      
          public void insertRow(int index) {
              wrapped.insertRow(index);
          }
      }
      
      // the factory that your SUT should be injected with and be 
      // using to wrap the table element with
      public interface IGwtWrapperFactory {
          public ITableElementWrapper wrap(TableElement te);
      }
      
      public class GwtWrapperFactory implements IGwtWrapperFactory {
          public ITableElementWrapper wrap(TableElement te) {
              return new TableElementWrapper(te);
          }
      }
      
    2. 使用Powermock,它是Mockito API extension,称为PowerMockito 来模拟本机方法。缺点是您有另一个依赖项要加载到您的测试项目中(我知道这可能是某些组织的问题,其中必须首先审核第 3 方库才能使用)。

    我个人会选择选项 2,因为 GWT 项目不太可能将自己的类包装在接口中(而且更有可能他们有更多需要模拟的本机方法)并且为自己做只包装本地方法调用只是浪费您的时间。

    【讨论】:

    • 不幸的是,我无法控制 TableElement 类 - 它属于外部库。不过 Powermock Mockito API 扩展看起来很有趣,我去看看。
    • 当你包装别人的东西时,拥有控制权。 :-) 这就是包装器的美妙之处,adaptersfaçades
    • 非常感谢您提供非常好的和详细的回答。包装将起作用,我可能会将其用作最后的手段,但就我的口味而言,它过于倾斜和复杂的生产代码仅用于测试目的:(。
    • @PiotrSobczyk 有用吗?在您编辑评论之前,我了解到您在使用 PowerMock 时遇到了一些问题。您确定您正确调用事物(经常发生)吗? stackoverflow.com/a/4916474/3713
    • 是的,现在可以使用了。我忘了包括@PrepareForTest(TableElement.class),这就是为什么没有工作。再次感谢您,您非常有帮助!
    【解决方案2】:

    以防其他人对此感到困惑:与此同时(May 2013GwtMockito 出现了,这解决了这个问题而无需 PowerMock 的开销。

    试试这个

    @RunWith(GwtMockitoTestRunner.class)
    public class MyTest {
    
        @Test
        public void test() throws Exception{
            TableElement table = mock(TableElement.class);
            table.insertRow(0);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-13
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-30
      相关资源
      最近更新 更多