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

Tou*_*uko 7 java jdbc resultset mocking stub

我正在测试一些使用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);
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

但是如果我没有引入新的方法public NClob getNClob(int columnIndex),那么这个类在Java 6下被破坏了 - 如果我在Java 5下介绍它们的类.

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

Tou*_*uko 3

好吧,经过一番思考,我最终得到了存根类,并用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...
}
Run Code Online (Sandbox Code Playgroud)

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