代码之家  ›  专栏  ›  技术社区  ›  Emil H

在任何地方都有JDBC的存根/模拟集吗?

  •  7
  • Emil H  · 技术社区  · 17 年前

    在过去的几年里,我一直在为单元测试数据库代码和随之而来的所有痛苦而挣扎。我发现这条现有的线索非常有启发性:

    接受答案的作者建议,为了验证生成的SQL,可以模拟整个数据库层。几个月前,当我第一次阅读答案时,我并没有考虑太多,但最近我发现了一些错误,这些错误是由错误生成的SQL、错误分配的字段等引起的。我确实意识到JDBC过于臃肿,而且容易出错,但在这一点上,切换到不同的东西是不可取的。

    所讨论的应用程序是数据源的批处理程序,直接使用JDBC而不是ORM。所有JDBC代码都被分成不同的DAO对象,其中每个对象都有自己的接口和存根,除了实际实现之外。这使我能够实现业务层的良好测试覆盖率,但数据库层的测试实际上是不存在的。

    是否存在JDBC(java.sql)接口的存根实现,可以将其注入DAO类中,并用于验证生成的sql,还可能发送回一些预编程的结果?

    6 回复  |  直到 9 年前
        1
  •  7
  •   seth    17 年前

    我不知道你有没有看过,但是有 MockRunner . 它提供了许多实现JDBC接口的类(以及其他J2EEC类)。这是 the JDBC mock objects . 也有不少 examples

        2
  •  4
  •   Geoffrey Wiseman    17 年前

    就我个人而言,我倾向于远离对大型复杂库的嘲笑;如果您确实需要直接测试DAO层,并且DAO直接与JDBC一起工作,那么您有三个明显的选择:

    1. 运行包含DAO和JDBC以及数据库的集成测试
    2. 在JDBC上添加一层,接口更薄,更适合模拟。

    我几乎总是选择1或2。因为在格式错误的SQL语法中有很多可能出现错误,我倾向于使用#1。然而,我意识到这不是你想要的

        3
  •  2
  •   Mercer Traieste    17 年前
        4
  •  2
  •   Lukas Eder    13 年前

    jOOQ 船上有 MockConnection 可以提供一个 MockDataProvider ,它比完整的JDBCAPI更容易实现。这篇博客文章展示了如何使用MockConnection: http://blog.jooq.org/2013/02/20/easy-mocking-of-your-database/

    例如:

    MockDataProvider provider = new MockDataProvider() {
    
        // Your contract is to return execution results, given a context
        // object, which contains SQL statement(s), bind values, and some
        // other context values
        @Override
        public MockResult[] execute(MockExecuteContext context) 
        throws SQLException {
    
            // Use ordinary jOOQ API to create an org.jooq.Result object.
            // You can also use ordinary jOOQ API to load CSV files or
            // other formats, here!
            DSLContext create = DSL.using(...);
            Result<MyTableRecord> result = create.newResult(MY_TABLE);
            result.add(create.newRecord(MY_TABLE));
    
            // Now, return 1-many results, depending on whether this is
            // a batch/multi-result context
            return new MockResult[] {
                new MockResult(1, result)
            };
        }
    };
    
    // Put your provider into a MockConnection and use that connection
    // in your application. In this case, with a jOOQ DSLContext:
    Connection connection = new MockConnection(provider);
    DSLContext create = DSL.using(connection, dialect);
    
    // Done! just use regular jOOQ API. It will return the values
    // that you've specified in your MockDataProvider
    assertEquals(1, create.selectOne().fetch().size());
    

    还有 MockFileDatabase

    # This is a sample test database for MockFileDatabase
    # Its syntax is inspired from H2's test script files
    
    # When this query is executed...
    select 'A' from dual;
    # ... then, return the following result
    > A
    > -
    > A
    @ rows: 1
    
    # Just list all possible query / result combinations
    select 'A', 'B' from dual;
    > A B
    > - -
    > A B
    @ rows: 1
    
    select "TABLE1"."ID1", "TABLE1"."NAME1" from "TABLE1";
    > ID1 NAME1
    > --- -----
    > 1   X
    > 2   Y
    @ rows: 2
    
        5
  •  1
  •   Nick Holt    17 年前

    虽然我是单元测试的忠实粉丝,但我发现它在DAOs中的价值有限。

    我所看到的是,虽然完全可以编写测试(使用任何模拟API)- JMock , EasyMock ,等等),它们通常直接工作(逻辑是如此的基本,它们怎么可能不工作)只有在您更改代码(例如添加值)时才会中断,这只会使它们成为代码库的负担。

    • 接通。
    • create语句。
    • 设置值。
    • 读取值(用于加载操作)。
    • 清理。

    来自DAO的错误通常发生在数据库中(密钥冲突、存储过程中的错误等),除非您作为一个整体运行系统,否则不会看到这些错误。

    这些天,我倾向于让更高级别的测试(集成等)在执行DAO代码时命中实际数据库,并希望尽早捕获我提到的那种错误。

        6
  •  0
  •   cchantep    7 年前

    如果您想根据各种JDBC情况测试持久层(ORM、DAO,…)是否按预期运行(例如,当它获得这样的结果集/更新计数时,它应该这样做和那样做),那么必须考虑Acolyte框架。

    它允许构建您通过处理程序管理的JDBC连接,因此您可以选择每个查询/更新返回的内容: https://github.com/cchantep/acolyte

    披露:这是我的框架。