【问题标题】:How to stub/mock JDBC ResultSet to work both with Java 5 and 6?如何存根/模拟 JDBC ResultSet 以同时使用 Java 5 和 6?
【发布时间】:2010-10-29 12:08:02
【问题描述】:

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

该软件应该在 Java 5 和 Java 6 上运行,因此测试也应该在这两个版本上运行。不幸的是,Java 6 引入了一堆新方法(这仍然不是什么大问题),它们返回一堆新的类/接口,这使得事情变得更加困难。 (例如见Frank Carver’s Punch Barrel - Java 6 breaks 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(例如)回调来让状态反映在返回值中,但是否有人有其他的——也许更好的——想法?

【问题讨论】:

    标签: java jdbc mocking resultset stub


    【解决方案1】:

    好吧,经过一番思考,我最终得到了存根类,并用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 中的存根类)。如果有人有其他想法,请随时回答=)

    【讨论】:

      【解决方案2】:

      我遇到了同样的问题,并使用代理实现解决了它。看起来效果不错。

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

      【讨论】:

        猜你喜欢
        • 2010-11-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-10
        • 1970-01-01
        • 2020-08-09
        相关资源
        最近更新 更多