很难对 spring 批处理作业进行“单元”测试,纯粹是因为与外部资源(例如数据库或文件等)的交互太多。我的方法有两个级别:
tasklet 中的各个方法正常进行单元测试,我只是直接从 JUnit 测试中调用这些方法,并使用通常的模拟或存根。
其次,我通过直接调用 main 方法从 JUnit 测试中运行批处理,并配备所有必要的基础设施。对于我的批处理作业,我需要一个数据库和一些输入文件。我的 JUnit 测试将该测试的所有必要文件复制到一个临时目录(我通常使用 maven target/it
)以及一个数据库(我的 MySQL 数据库的副本以 HSQLDB 格式保存)。然后我Main.main()
直接用正确的参数调用,让批处理运行然后检查结果,检查是否生成了正确的文件,数据库是否已正确更改等。
作为一种工作方式,这有几个优点。
- 我可以从 Eclipse 运行这些测试,从而缩短了调试周期,因为我不需要每次都构建完整的包来测试它。
- 它们很容易合并到构建中,我只是将它们包含在 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 启动它. 有时这可能有点繁琐。