如何存根/模拟 JDBC ResultSet 以同时使用 Java 5 和 6?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/919544/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to stub/mock JDBC ResultSet to work both with Java 5 and 6?
提问by Touko
I'm testing some of my classes working with JDBC statements etc and now I got problem with JDBC ResultSet interface:
我正在测试我的一些使用 JDBC 语句等的类,现在我遇到了 JDBC ResultSet 接口的问题:
The software should run both with Java 5 and Java 6 and hence the tests should also be run with both versions. Unfortunately Java 6 has introduced a bunch of new methods (which is still not a big deal) that return a bunch of new classes/interfaces, which makes the things more difficult. (see Frank Carver's Punch Barrel - Java 6 breaks JDBCfor example)
该软件应该在 Java 5 和 Java 6 上运行,因此测试也应该在两个版本上运行。不幸的是,Java 6 引入了一堆新方法(这仍然不是什么大问题),它们返回一堆新类/接口,这让事情变得更加困难。(例如,参见Frank Carver 的 Punch Barrel - Java 6 破坏 JDBC)
Before finding out these version differences, I considered between stubbing and mocking and ended up with stubbing because the ResultSet has internal state (current row handled) that is more natural to me to work with stubs, as :
在找出这些版本差异之前,我在存根和模拟之间进行了考虑,并以存根结束,因为 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);
}
// ...
}
But if I don't introduce the new methods as public NClob getNClob(int columnIndex), the class is broken under Java 6 - if I introduce them the class in broken under Java 5.
但是,如果我不将新方法作为 引入public NClob getNClob(int columnIndex),则该类在 Java 6 下已损坏 - 如果我向它们引入 Java 5 下已损坏的类。
I can work with mockito (for example) callbacks to have the state being reflected with the return values but does somebody have some other - maybe more nice - idea?
我可以使用 mockito(例如)回调来让状态反映在返回值中,但是有人有其他一些 - 也许更好 - 的想法吗?
采纳答案by Touko
Well, after some thinking I ended up having the stub class as there and mocking it with Mockitoas:
好吧,经过一番思考,我最终将存根类放在那里,并用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<Object>() {
public Object answer(InvocationOnMock invocation) throws Throwable {
return contents.getObject(getIntArgument(invocation));
}
});
// a bunch of similar when(...).thenAnswer(...) constructs...
}
(stub class in StubResultSetContents). If somebody has some other ideas, feel free to answer =)
(StubResultSetContents 中的存根类)。如果有人有其他想法,请随时回答 =)
回答by HJN
I had the same problem and solved it using a Proxy implementation. It seems like it's working pretty good.
我遇到了同样的问题并使用代理实现解决了它。看起来它工作得很好。
public class TestResultSet implements InvocationHandler {
public static ResultSet createProxy(HashMap<Object, Object>[] 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;
}
}

