5

在 Spring Batch 作业中测试以下场景的方法是什么:

1)一个独立的tasklet在spring批处理作业的一个步骤中运行。

2) 一个由几个步骤组成的作业,其中一些步骤具有 itemreader、itemprocessor、itemwriters,而一些步骤具有 tasklet。

3) itemreader,其中对 item reader 的输入查询是一个非常复杂的 sql 查询,具有来自许多表的连接 - 这种情况不允许清空所有使用的表并用虚拟数据填充它们以进行测试。换句话说,在现实世界中可能存在无法清空表进行测试的情况。在这种情况下应该采取什么方法?

如果我在这个论坛上得到关于要采取的方法的一点帮助,我想准备一个示例套件,其中包含有关测试具有不同工作场景的 spring 批处理作业的示例。

4

1 回答 1

8

很难对 spring 批处理作业进行“单元”测试,纯粹是因为与外部资源(例如数据库或文件等)的交互太多。我的方法有两个级别:

tasklet 中的各个方法正常进行单元测试,我只是直接从 JUnit 测试中调用这些方法,并使用通常的模拟或存根。

其次,我通过直接调用 main 方法从 JUnit 测试中运行批处理,并配备所有必要的基础设施。对于我的批处理作业,我需要一个数据库和一些输入文件。我的 JUnit 测试将该测试的所有必要文件复制到一个临时目录(我通常使用 maven target/it)以及一个数据库(我的 MySQL 数据库的副本以 HSQLDB 格式保存)。然后我Main.main()直接用正确的参数调用,让批处理运行然后检查结果,检查是否生成了正确的文件,数据库是否已正确更改等。

作为一种工作方式,这有几个优点。

  1. 我可以从 Eclipse 运行这些测试,从而缩短了调试周期,因为我不需要每次都构建完整的包来测试它。
  2. 它们很容易合并到构建中,我只是将它们包含在 maven 的故障安全插件中。

有几个警告:

您需要在 SecurityManager 中运行 main 方法。如果您的 main 调用 System.exit(),您不希望 JVM 停止。有关 SecurityManager 的示例,请参阅org.junit.tests.running.core.MainRunner。这被称为:

Integer exitValue = new MainRunner().runWithCheckForSystemExit(new Runnable() {
    public void run() {
    Main.main(new String[] {});
  }
});

使用上述方法,您可以断言批处理调用 System.exit() 在失败时使用正确的值,也允许测试失败条件。

其次,您可以从 JUnit 测试中进行大量设置,但不能全部完成,因此,例如,如果您需要 FTP 服务器,我通常在故障安全插件运行之前从 maven 而不是 JUnit 启动它. 有时这可能有点繁琐。

于 2012-10-30T10:05:53.293 回答