java - 每次运行 SQL 语句时更改 Mocked ResultSet 值

标签 java sql unit-testing mockrunner

我正在使用 Mockrunner 为 select 语句创建模拟结果集。我有一个执行 select 语句(返回单个值)的循环。我想让结果集每次都返回不同的值,但是我一直无法找到任何关于如何根据调用语句的次数指定结果集返回值的信息。这是代码的伪代码片段:

在测试代码中:

String selectSQL = "someselectStmt";
StatementResultSetHandler stmtHandler = conn.GetStatementResultSetHandler();
MockResultSet result = stmtHandler.createResultSet();
result.addRow(new Integer[]{new Integer(1)});
stmtHandler.prepareResultSet(selectSQL, result);

在实际目标类中:

Integer[] Results = getResults(selectSQL);

while(Results.length != 0){
    //do some stuff that change what gets returned in the select stmt
    Results = getResults(selectSQL)
}

所以基本上我想在第一次通过时返回 1,在第二次返回 2,在第三次返回任何内容。到目前为止,我还没有发现任何可以利用的东西来实现这一目标。模拟的 select 语句将始终返回与它相关联的最后一个结果集(例如,如果我创建了两个 MockResultSets 并将它们与相同的 select stmt 相关联)。这个想法可行吗?

最佳答案

在 Java 和 SQL 中工作的循环控制流

如果您使用 Java 编写此代码,可以通过循环控制流语句(例如 do-while-loop)来实现一种使代码执行调用返回不同、有序结果的方法。 .这个维基百科引用有一个很好的讨论,使用 Java 和不同编程语言中的实现之间的 do-while-loop 的对比。

通过观察产生的一些额外影响:

您使用 Mockrunner 工具的一个线索:

The mocked select statement will always return whatever the last result set was to be associated with it (for instance if I created two MockResultSets and associated both with the same select stmt)

之所以如此,是因为 SELECT 语句实际上也必须更改,否则重复查询也会重复结果输出。一条线索是,您的 SQL 在整个代码执行过程中都以文字字符串值的形式存在。可以通过代码和简单的字符串操作来更改字符串。

String selectSQL = "someselectStmt";
StatementResultSetHandler stmtHandler = conn.GetStatementResultSetHandler();
MockResultSet result = stmtHandler.createResultSet();
result.addRow(new Integer[]{new Integer(1)});
stmtHandler.prepareResultSet(selectSQL, result);

除了selectSQL 变量外,还为数字变量添加一行以跟踪SQL 语句执行了多少次:

Int queryLoopCount = 0;

在下面的目标类中:

Integer[] Results = getResults(selectSQL);

while(Results.length != 0){
//do some stuff that change what gets returned in the select stmt
Results = getResults(selectSQL)
}

尝试按照此示例重写此 WHILE 循环控件。在您的伪代码中,您将继续从对 getResults(selectSQL); 的调用中提取相同的数据,因为通过代码进行的每一次查询都保持相同。

设置测试模式和示例 SQL 语句

这是一个使用单个 MySQL 表的小处理,该表包含要馈送到某个结果集中的“testdata”输出。 ID 列可以是一种唯一标识每个不同记录或“测试用例”的方法

SQL Fiddle

MySQL 5.5.32 架构设置:

CREATE TABLE testCaseData 
    (
     id int primary key,
     testdata_col1 int,
     testdata_col2 varchar(20),
     details varchar(30)
    );

INSERT INTO testCaseData
(id, testdata_col1, testdata_col2, details)
VALUES
(1, 2021, 'alkaline gab', 'First Test'),
(2, 322, 'rebuked girdle', '2nd Test'),
(3, 123, 'municipal shunning', '3rd Test'),
(4, 4040, 'regal limerick', 'Skip Test'),
(5, 5550, 'admonished hundredth', '5th Test'),
(6, 98, 'docile pushover', '6th Test'),
(7, 21, 'mousiest festivity', 'Last Test');

commit;

查询1查看所有测试数据:

SELECT id, testdata_col1, testdata_col2, details
  FROM testCaseData

Results :

| ID | TESTDATA_COL1 |        TESTDATA_COL2 |    DETAILS |
|----|---------------|----------------------|------------|
|  1 |          2021 |         alkaline gab | First Test |
|  2 |           322 |       rebuked girdle |   2nd Test |
|  3 |           123 |   municipal shunning |   3rd Test |
|  4 |          4040 |       regal limerick |  Skip Test |
|  5 |          5550 | admonished hundredth |   5th Test |
|  6 |            98 |      docile pushover |   6th Test |
|  7 |            21 |   mousiest festivity |  Last Test |

查询2只查询表中的第一条记录:

SELECT id, testdata_col1, testdata_col2, details
  FROM testCaseData
 WHERE id = 1

Results :

| ID | TESTDATA_COL1 | TESTDATA_COL2 |    DETAILS |
|----|---------------|---------------|------------|
|  1 |          2021 |  alkaline gab | First Test |

查询3查询表内的特定测试记录:

SELECT id, testdata_col1, testdata_col2, details
  FROM testCaseData
 WHERE id = 2

Results :

| ID | TESTDATA_COL1 |  TESTDATA_COL2 |  DETAILS |
|----|---------------|----------------|----------|
|  2 |           322 | rebuked girdle | 2nd Test |

查询 4 ​​返回并限制输出集大小:

SELECT id, testdata_col1, testdata_col2, details
  FROM testCaseData
 WHERE id < 5

Results :

| ID | TESTDATA_COL1 |      TESTDATA_COL2 |    DETAILS |
|----|---------------|--------------------|------------|
|  1 |          2021 |       alkaline gab | First Test |
|  2 |           322 |     rebuked girdle |   2nd Test |
|  3 |           123 | municipal shunning |   3rd Test |
|  4 |          4040 |     regal limerick |  Skip Test |

编写参数化 SQL 语句

我不知道语法上的这种差异是否会产生与您的伪代码完全相同的结果,但我从我知道已经有效的代码结构引用中推荐它。

set condition value before loop
do{
    // do some work
    // update condition value
}while(condition);

WHILE 条件位于语句的末尾,应该基于对循环 block 中值的更改。我们现在将介绍第二个变量,一个跟踪循环迭代次数的整数:

String selectSQL = "someselectStmt";
String[] Results; = getResults(selectSQL);

// set condition value before loop 
queryLoopCount = 0

do{
    // do some work
    Results = getResults(selectSQL);

    // update condition value
    queryLoopCount = queryLoopcount + 1;

}while(queryLoopCount < 6);

selectSQL 的来源:

SELECT id, testdata_col1, testdata_col2, details
  FROM testCaseData
 WHERE id = 2;

并使用内置参数适应:

selectSQL = 'SELECT id, testdata_col1, testdata_col2, details
  FROM testCaseData
 WHERE id = ' + queryLoopCount;

混合字符串和整数值可能不会像 this reference 中那样成为问题。 on concatenated(+) values 建议:任何连接到字符串的内容都将转换为字符串(例如,“weight =” + 千克)。

特殊案例要求的想法

  • 您可以引入自己的编号顺序,让每个案例的记录在引用表中循环。通过引入 ORDER BY 语句并更改键 ORDER BY 值,有很多可能性。

  • “跳过”案例。在 Do-While 循环中,添加 IF-THEN 语句以有条件地跳过特定记录。

    set condition value before loop
    do{
    
        if ( queryLoopCount <> 4 ) {
        // do some work}
    
        // update condition value
        queryLoopCount = queryLoopCount + 1;
    
    }while(condition);
    

    使用 if-then 循环,此代码示例将处理所有测试记录,但将跳过 ID = 4 的记录并继续执行直到满足 while 循环条件。

关于java - 每次运行 SQL 语句时更改 Mocked ResultSet 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23134946/

相关文章:

c++ - 在测试工具下获取当前可执行目录失败

java - 如何从 Java 访问外部 Jar 中的资源/配置/文本文件?

java - 为什么我的 JVM 堆大小从 2gigs 猛增到 8gigs?

sql - 创建一个只能在当前连接中访问的(临时?)表

SQL OVER (Partition by) - 处理空值

sql - TSQL,如何对行进行分组?

javascript - 单元测试返回 TypeError : undefined is not a constructor error message

java - 用于在测试字符串中重复文本的正则表达式

java - jpa插入行时应返回用于主键列的序列号

android - 在生产代码中包含 Toast 的单元测试失败