在过去的几年里,我一直在努力研究单元测试数据库代码以及随之而来的所有痛苦。我发现这个现有的帖子我觉得非常有启发性:
接受回答的作者表示,为了验证生成的SQL,模拟整个数据库层可能很有用。几个月前,当我第一次阅读答案时,我没有想太多,但最近我发现了SQL生成错误,错误分配字段等导致的一些错误。我确实意识到JDBC相当臃肿且容易出错,但此时不能选择切换到不同的东西。
有问题的应用程序是数据源的批处理器,直接使用JDBC而不是ORM。除了实际的实现之外,所有JDBC代码都被分成不同的DAO对象,其中每个对象都有自己的接口和存根。这使我能够实现业务层的良好测试覆盖率,但数据库层的测试几乎不存在。
是否存在JDBC(java.sql)接口的现有存根实现,可以将其注入DAO类并用于验证生成的SQL并可能发回一些预编程的结果?
答案 0 :(得分:7)
我不知道你是否看过它,但有MockRunner。它提供了许多实现JDBC接口(以及其他J2EE类)的类。这是the JDBC mock objects。还有不少examples。
答案 1 :(得分:4)
听起来你在DAO代码中遇到了问题?否则,DAO层是进行模拟的明显位置,但是如果你试图测试DAO,那么你需要模拟下面的那些。
就个人而言,我倾向于远离嘲弄大型复杂的图书馆;如果您确实需要直接测试DAO层并且DAO直接使用JDBC,那么您有三个明显的选择:
我几乎总是选择#1或#2。因为在格式错误的SQL语法等方面存在大量错误的可能性,所以我倾向于倾向于#1。然而,我意识到这不是你所要求的。 ;)
答案 2 :(得分:2)
您可以使用dbunit直接测试数据库。
答案 3 :(得分:2)
jOOQ附带MockConnection
,可以提供MockDataProvider
,这比完整的JDBC API更容易实现。这篇博客文章展示了如何使用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
,它可以帮助您通过编写如下文本文件来匹配虚拟结果和SQL字符串:
# 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
答案 4 :(得分:1)
虽然我一般都非常喜欢单元测试,但我发现DAO的价值有限。
我所看到的是完全有可能编写测试(使用任何模拟API - JMock,EasyMock等),它们通常是直接工作的(逻辑)如此基本,他们怎么可能不会)只在你更改代码时断开(例如添加一个值),这只会使它们成为代码库的负担。
我认为这是因为我的DAO通常遵循以下形式:
源自DAO的错误通常发生在数据库中(密钥违规,存储过程中的错误等),除非您作为一个整体运行系统,否则您不会看到这些错误。
这些天我倾向于让更高级别的测试 - 集成等 - 运用DAO代码来实现这样做,并希望能够及早发现我提到的那种错误。
答案 5 :(得分:0)
如果你想测试持久层(ORM,DAO,...)根据各种JDBC情况按预期运行(例如,当它获得这样的结果集/更新计数时,那么它应该这样做那样),然后是Acolyte必须考虑框架。
它允许构建您通过处理程序管理的JDBC连接,因此您可以选择为每个查询/更新返回的内容:https://github.com/cchantep/acolyte
披露:这是我的框架。