Как заглушки / макеты JDBC ResultSet для работы как с Java 5 и 6? - PullRequest
7 голосов
/ 28 мая 2009

Я тестирую некоторые из моих классов, работающих с операторами JDBC и т. Д., И теперь у меня возникла проблема с интерфейсом JDBC ResultSet:

Программное обеспечение должно работать как с Java 5, так и с Java 6, и, следовательно, тесты также должны выполняться с обеими версиями. К сожалению, в Java 6 появилось множество новых методов (что пока не так уж важно), которые возвращают кучу новых классов / интерфейсов, что усложняет ситуацию. (см. Штанга Фрэнка Карвера - 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 (например), чтобы состояние отражалось с возвращаемыми значениями, но есть ли у кого-нибудь другая, может быть, более приятная идея?

Ответы [ 2 ]

3 голосов
/ 28 мая 2009

Что ж, после некоторого размышления у меня получился класс заглушки, и я сменил его над 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...
}

(класс-заглушка в StubResultSetContents). Если у кого-то есть другие идеи, не стесняйтесь отвечать =)

0 голосов
/ 08 октября 2009

У меня была такая же проблема, и я решил ее с помощью реализации Proxy. Кажется, что он работает довольно хорошо.

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;
    }

}
...