7

JDBCステートメントなどを使用して動作するクラスの一部をテストしていますが、JDBCResultSetインターフェイスで問題が発生しました。

ソフトウェアはJava5とJava6の両方で実行する必要があるため、テストも両方のバージョンで実行する必要があります。残念ながら、Java 6は、一連​​の新しいクラス/インターフェースを返す一連の新しいメソッド(まだ大したことではありません)を導入しました。これにより、事態はさらに困難になります。(FrankCarverのPunchBarrelを参照してください-たとえば、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で壊れます。クラスを導入すると、Java5で壊れます。

mockito(たとえば)コールバックを使用して、状態が戻り値に反映されるようにすることはできますが、他の誰か(おそらくもっといいアイデア)がありますか?

4

2 に答える 2

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

(StubResultSetContentsのスタブクラス)。誰か他のアイデアがあれば、遠慮なく答えてください=)

于 2009-05-28T07:49:38.327 に答える
0

私は同じ問題を抱えていて、プロキシ実装を使用して解決しました。それはかなりうまくいっているようです。

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

}
于 2009-10-08T12:24:41.340 に答える