我有一个简单的测试用例:
@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)
我相信这与插入行方法的本机有关。有什么方法或解决方法可以用 Mockito 模拟这些方法吗?
根据这个 Google Group 线程,Mockito 本身似乎无法模拟本机方法。但是,您有两个选择:
- 将
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); } }
- 使用Powermock,它是名为
PowerMockito
的Mockito API扩展来模拟本机方法。缺点是您需要将另一个依赖项加载到测试项目中(我知道这可能是某些组织的问题,其中必须首先审核第三方库才能使用)。
就我个人而言,我会选择选项 2,因为 GWT 项目不太可能将自己的类包装在接口中(而且他们更有可能有更多需要模拟的本机方法),并且自己只包装本机方法调用只是浪费您的时间。
万一其他人对此感到困惑:与此同时(2013 年 5 月),GwtMockito 出现了,它解决了这个问题,而没有 PowerMock 的开销。
试试这个
@RunWith(GwtMockitoTestRunner.class)
public class MyTest {
@Test
public void test() throws Exception{
TableElement table = mock(TableElement.class);
table.insertRow(0);
}
}