模拟 jooq 选择请求

Hay*_*ysh 5 java junit mockito jooq

我的服务是 jooq select inmyMethod()

Result<MyRecord> records = dsl.selectFrom(MyTable).fetch();
Run Code Online (Sandbox Code Playgroud)

我尝试使用mockito 编写单元测试。我想模拟我的 dsl 并在调用时得到 2 个不同的结果service.myMethod()

Mockito.when(dsl.selectFrom(MyTable)).thenReturn(result)
Run Code Online (Sandbox Code Playgroud)

但这不起作用。我如何模拟我的选择请求?

Luk*_*der 6

模拟 jOOQ API

如果您想模拟 jOOQ API,您可以模拟的有趣方法是各种fetch()方法execute(),因为它们的作用类似于 jOOQ DSL API 的“终端”方法。所有中间方法都应该产生新的模拟,而不是实际结果。

然而,由于 jOOQ 的 DSL 很大,您可能会忽略各种边缘情况,因此我认为完全模拟它可能效果不太好。

模拟 JDBC API

如果你真的想模拟 jOOQ API,我宁愿在 JDBC 级别上模拟它。jOOQ 实现了一个模拟 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();
Run Code Online (Sandbox Code Playgroud)

然后(简化):

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

该模拟实现还有一个开箱即用的基于文件的版本,它MockFileDatabase使用正则表达式来匹配 SQL 字符串,并提供基于文本的语法来构造查询的结果集。

一般模拟数据库

请注意,模拟并不是测试数据库交互的好方法——在简单的情况下,它只能让您到目前为止。集成测试是一种更好、更彻底的方法。如果必须,请使用内存数据库,但最好通过testcontainers之类的工具使用生产数据库产品(例如 Oracle、PostgreSQL 等) 。