模拟 jooq select 请求
mock jooq select request
我在 myMethod()
为 jooq select 提供服务
Result<MyRecord> records = dsl.selectFrom(MyTable).fetch();
我尝试使用 mockito 编写单元测试。我想模拟我的 dsl 并在调用 service.myMethod()
时得到 2 个不同的结果
Mockito.when(dsl.selectFrom(MyTable)).thenReturn(result)
但是没用。如何模拟我的 select 请求?
模拟 jOOQ API
如果您想模拟 jOOQ API,您可以模拟的有趣方法是各种 fetch()
方法或 execute()
方法,因为它们的作用类似于 "terminal" jOOQ DSL 的方法 API。所有中间方法都应该产生新的模拟,而不是实际结果。
但是,由于 jOOQ 的 DSL 非常庞大,您可能会忽略各种边缘情况,因此我认为完全模拟它可能效果不佳。
嘲笑 JDBC API
如果你真的想模拟 jOOQ API,我宁愿在 JDBC 水平上模拟它。 jOOQ 实现了一个 mock JDBC Connection,允许使用单个 lambda 表达式模拟整个 JDBC,您可以在其中做这样的事情(来自手册):
MockDataProvider provider = new MyProvider();
MockConnection connection = new MockConnection(provider);
DSLContext ctx = DSL.using(connection, SQLDialect.ORACLE);
Result<BookRecord> result = ctx.selectFrom(BOOK).where(BOOK.ID.eq(5)).fetch();
然后(简体):
public class MyProvider implements MockDataProvider {
@Override
public MockResult[] execute(MockExecuteContext ctx) throws SQLException {
DSLContext ctx = DSL.using(SQLDialect.ORACLE);
MockResult[] mock = new MockResult[1];
String sql = ctx.sql();
if (sql.toUpperCase().startsWith("DROP")) {
throw new SQLException("Statement not supported: " + sql);
}
else if (sql.toUpperCase().startsWith("SELECT")) {
Result<Record2<Integer, String>> result =
ctx.newResult(AUTHOR.ID, AUTHOR.LAST_NAME);
result.add(cctx
.newRecord(AUTHOR.ID, AUTHOR.LAST_NAME)
.values(1, "Orwell"));
mock[0] = new MockResult(1, result);
}
return mock;
}
}
这个模拟实现还有一个开箱即用的基于文件的版本,MockFileDatabase
,它使用正则表达式匹配 SQL 字符串,并提供基于文本的语法来构造结果为您的查询设置。
一般模拟数据库
请注意,模拟不是测试数据库交互的好方法 - 在简单的情况下,它只能让你到此为止。更好、更彻底的方法是集成测试。如果必须,使用内存数据库,但最好通过 testcontainers.
之类的方式使用生产数据库产品(例如 Oracle、PostgreSQL 等)
我在 myMethod()
Result<MyRecord> records = dsl.selectFrom(MyTable).fetch();
我尝试使用 mockito 编写单元测试。我想模拟我的 dsl 并在调用 service.myMethod()
Mockito.when(dsl.selectFrom(MyTable)).thenReturn(result)
但是没用。如何模拟我的 select 请求?
模拟 jOOQ API
如果您想模拟 jOOQ API,您可以模拟的有趣方法是各种 fetch()
方法或 execute()
方法,因为它们的作用类似于 "terminal" jOOQ DSL 的方法 API。所有中间方法都应该产生新的模拟,而不是实际结果。
但是,由于 jOOQ 的 DSL 非常庞大,您可能会忽略各种边缘情况,因此我认为完全模拟它可能效果不佳。
嘲笑 JDBC API
如果你真的想模拟 jOOQ API,我宁愿在 JDBC 水平上模拟它。 jOOQ 实现了一个 mock JDBC Connection,允许使用单个 lambda 表达式模拟整个 JDBC,您可以在其中做这样的事情(来自手册):
MockDataProvider provider = new MyProvider();
MockConnection connection = new MockConnection(provider);
DSLContext ctx = DSL.using(connection, SQLDialect.ORACLE);
Result<BookRecord> result = ctx.selectFrom(BOOK).where(BOOK.ID.eq(5)).fetch();
然后(简体):
public class MyProvider implements MockDataProvider {
@Override
public MockResult[] execute(MockExecuteContext ctx) throws SQLException {
DSLContext ctx = DSL.using(SQLDialect.ORACLE);
MockResult[] mock = new MockResult[1];
String sql = ctx.sql();
if (sql.toUpperCase().startsWith("DROP")) {
throw new SQLException("Statement not supported: " + sql);
}
else if (sql.toUpperCase().startsWith("SELECT")) {
Result<Record2<Integer, String>> result =
ctx.newResult(AUTHOR.ID, AUTHOR.LAST_NAME);
result.add(cctx
.newRecord(AUTHOR.ID, AUTHOR.LAST_NAME)
.values(1, "Orwell"));
mock[0] = new MockResult(1, result);
}
return mock;
}
}
这个模拟实现还有一个开箱即用的基于文件的版本,MockFileDatabase
,它使用正则表达式匹配 SQL 字符串,并提供基于文本的语法来构造结果为您的查询设置。
一般模拟数据库
请注意,模拟不是测试数据库交互的好方法 - 在简单的情况下,它只能让你到此为止。更好、更彻底的方法是集成测试。如果必须,使用内存数据库,但最好通过 testcontainers.
之类的方式使用生产数据库产品(例如 Oracle、PostgreSQL 等)