如何使用Java 5和6来存根/模拟JDBC ResultSet?

我正在测试一些使用JDBC语句等的类,现在我遇到了JDBC ResultSet接口的问题:

该软件应该与Java 5和Java 6一起运行,因此测试也应该与两个版本一起运行。 不幸的是,Java 6引入了一堆新方法(这仍然不是什么大问题),它返回了一堆新的类/接口,这使事情变得更加困难。 (参见Frank Carver的Punch Barrel -例如Java 6打破了JDBC )

在找出这些版本差异之前,我考虑了在存根和模拟之间并最终使用了存根,因为ResultSet具有内部状态(当前行处理),这对我来说更自然地使用存根,如下所示:

public class StubResultSet implements ResultSet { private Object[][] data; private int currentRow = -1; private boolean closed = false; public StubResultSet(Object[][] data) { this.data = data; } public Object getObject(int columnIndex) throws SQLException { checkClosed(); return data[currentRow][columnIndex]; } public String getString(int columnIndex) throws SQLException { checkClosed(); return (String) getObject(columnIndex); } // ... } 

但是如果我不将新方法作为public NClob getNClob(int columnIndex)引入,那么这个类在Java 6下被破坏 – 如果我在Java 5下引入它们的类。

我可以使用mockito(例如)回调来使状态反映回返值,但是有人还有其他一些 – 也许更好 – 想法吗?

好吧,经过一番思考后,我最终得到了存根类,并用Mockito嘲笑它:

 public static ResultSet initMock(Object[][] data) throws SQLException { final StubResultSetContents contents = new StubResultSetContents(data); ResultSet rs = mock(ResultSet.class, RETURNS_SMART_NULLS); when(rs.getObject(anyInt())).thenAnswer(new Answer() { public Object answer(InvocationOnMock invocation) throws Throwable { return contents.getObject(getIntArgument(invocation)); } }); // a bunch of similar when(...).thenAnswer(...) constructs... } 

(StubResultSetContents中的存根类)。 如果有人有其他想法,请随时回答=)

我有同样的问题,并使用代理实现解决了它。 看起来它的工作非常好。

 public class TestResultSet implements InvocationHandler { public static ResultSet createProxy(HashMap[] rows) { return (ResultSet) Proxy.newProxyInstance(ResultSet.class.getClassLoader(), new Class[] { ResultSet.class }, new TestResultSet(rows)); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // Find the equivalent method in the proxy class. Method m = TestResultSet.class.getMethod(method.getName(), method.getParameterTypes()); if(m == null) { throw new SQLException("Unsupported method " + method.getName()); } return m.invoke(this, args); } // Method implementations follow here (only one supplied as an example) public boolean isFirst() throws SQLException { return index ==0; } }