首页 > 其他分享 >Spring Batch -单元测试

Spring Batch -单元测试

时间:2022-12-16 13:33:45浏览次数:41  
标签:示例 批处理 Spring 单元测试 StepExecution Batch 测试 new public

Spring Batch -单元测试_bc

与其他应用程序样式一样,对编写的任何代码进行单元测试非常重要。 作为批处理作业的一部分。Spring 核心文档涵盖了如何单元和集成 用 Spring 进行了非常详细的测试,因此这里不再重复。然而,重要的是, 思考如何“端到端”测试批处理作业,这就是本章介绍的内容。 该项目包括促进此端到端测试的类 方法。​​spring-batch-test​

创建单元测试类

要使单元测试运行批处理作业,框架必须加载作业的 .两个批注用于触发此行为:​​ApplicationContext​

  • ​@SpringJUnitConfig​​指示类应使用 Spring 的 JUnit 设施
  • ​@SpringBatchTest​​在测试上下文中注入 Spring 批处理测试实用程序(例如 和 )JobLauncherTestUtilsJobRepositoryTestUtils

如果测试上下文包含单个 Bean 定义,则此 Bean 将在 中自动连线。否则,作业 应在 上手动设置“测试”。​​Job​​​​JobLauncherTestUtils​​​​JobLauncherTestUtils​

以下 Java 示例显示了正在使用的注释:

使用 Java 配置

@SpringBatchTest
@SpringJUnitConfig(SkipSampleConfiguration.class)
public class SkipSampleFunctionalTests { ... }

以下 XML 示例显示了正在使用的批注:

使用 XML 配置

@SpringBatchTest
@SpringJUnitConfig(locations = { "/simple-job-launcher-context.xml",
"/jobs/skipSampleJob.xml" })
public class SkipSampleFunctionalTests { ... }

批处理作业的端到端测试

“端到端”测试可以定义为测试批处理作业的完整运行 从头到尾。这允许设置测试条件、执行作业、 并验证最终结果。

考虑一个从数据库读取并写入平面文件的批处理作业示例。 测试方法首先使用测试数据设置数据库。它清除表,然后插入 10 条新记录。然后,测试使用该方法启动 。该方法由类提供。该类还提供了方法,该方法允许测试给出特定的参数。方法 返回对象,这对于断言特定信息很有用 关于运行。在以下情况下,测试验证 状态为 。​​CUSTOMER​​​​Job​​​​launchJob()​​​​launchJob()​​​​JobLauncherTestUtils​​​​JobLauncherTestUtils​​​​launchJob(JobParameters)​​​​launchJob()​​​​JobExecution​​​​Job​​​​Job​​​​COMPLETED​

以下清单显示了 XML 配置样式中的 JUnit 5 示例:

基于 XML 的配置

@SpringBatchTest
@SpringJUnitConfig(locations = { "/simple-job-launcher-context.xml",
"/jobs/skipSampleJob.xml" })
public class SkipSampleFunctionalTests {

@Autowired
private JobLauncherTestUtils jobLauncherTestUtils;

private JdbcTemplate jdbcTemplate;

@Autowired
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}

@Test
public void testJob(@Autowired Job job) throws Exception {
this.jobLauncherTestUtils.setJob(job);
this.jdbcTemplate.update("delete from CUSTOMER");
for (int i = 1; i <= 10; i++) {
this.jdbcTemplate.update("insert into CUSTOMER values (?, 0, ?, 100000)",
i, "customer" + i);
}

JobExecution jobExecution = jobLauncherTestUtils.launchJob();


Assert.assertEquals("COMPLETED", jobExecution.getExitStatus().getExitCode());
}
}

以下清单显示了 Java 配置样式中的 JUnit 5 示例:

基于 Java 的配置

@SpringBatchTest
@SpringJUnitConfig(SkipSampleConfiguration.class)
public class SkipSampleFunctionalTests {

@Autowired
private JobLauncherTestUtils jobLauncherTestUtils;

private JdbcTemplate jdbcTemplate;

@Autowired
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}

@Test
public void testJob(@Autowired Job job) throws Exception {
this.jobLauncherTestUtils.setJob(job);
this.jdbcTemplate.update("delete from CUSTOMER");
for (int i = 1; i <= 10; i++) {
this.jdbcTemplate.update("insert into CUSTOMER values (?, 0, ?, 100000)",
i, "customer" + i);
}

JobExecution jobExecution = jobLauncherTestUtils.launchJob();


Assert.assertEquals("COMPLETED", jobExecution.getExitStatus().getExitCode());
}
}

测试各个步骤

对于复杂的批处理作业,端到端测试方法中的测试用例可能会变成 不可收拾。在这些情况下,使用测试用例来测试单个可能更有用 自己踩踏。该类包含一个名为 的方法。 它采用步骤名称并仅运行该特定.这种方法允许 更有针对性的测试,让测试只为该步骤设置数据并验证其 直接结果。下面的示例演示如何使用该方法按名称加载​​AbstractJobTests​​​​launchStep​​​​Step​​​​launchStep​​​​Step​

JobExecution jobExecution = jobLauncherTestUtils.launchStep("loadFileStep");

测试步进范围的组件

通常,在运行时为步骤配置的组件使用步骤范围和 后期绑定以从步骤或作业执行注入上下文。这些很难测试,因为 独立组件,除非您有办法将上下文设置为它们在一个步骤中 执行。这是 Spring Batch 中两个组件的目标:和 。​​StepScopeTestExecutionListener​​​​StepScopeTestUtils​

侦听器在类级别声明,其工作是创建步骤执行 每个测试方法的上下文,如以下示例所示:

@SpringJUnitConfig
@TestExecutionListeners( { DependencyInjectionTestExecutionListener.class,
StepScopeTestExecutionListener.class })
public class StepScopeTestExecutionListenerIntegrationTests {

// This component is defined step-scoped, so it cannot be injected unless
// a step is active...
@Autowired
private ItemReader<String> reader;

public StepExecution getStepExecution() {
StepExecution execution = MetaDataInstanceFactory.createStepExecution();
execution.getExecutionContext().putString("input.data", "foo,bar,spam");
return execution;
}

@Test
public void testReader() {
// The reader is initialized and bound to the input data
assertNotNull(reader.read());
}

}

有两个.一个是常规的弹簧测试框架,它 处理来自配置的应用程序上下文的依赖项注入以注入读取器。 另一个是春季批次。它通过寻找一个 测试用例中的工厂方法,使用它作为 测试方法,就好像该执行在运行时处于活动状态一样。工厂方法 通过其签名检测到(它必须返回 )。如果工厂方法是 未提供,则创建默认值。​​TestExecutionListeners​​​​StepScopeTestExecutionListener​​​​StepExecution​​​​Step​​​​StepExecution​​​​StepExecution​

从 v4.1 开始,将 和 作为测试执行侦听器导入 如果测试类用 .前面的测试 示例可以配置如下:​​StepScopeTestExecutionListener​​​​JobScopeTestExecutionListener​​​​@SpringBatchTest​

@SpringBatchTest
@SpringJUnitConfig
public class StepScopeTestExecutionListenerIntegrationTests {

// This component is defined step-scoped, so it cannot be injected unless
// a step is active...
@Autowired
private ItemReader<String> reader;

public StepExecution getStepExecution() {
StepExecution execution = MetaDataInstanceFactory.createStepExecution();
execution.getExecutionContext().putString("input.data", "foo,bar,spam");
return execution;
}

@Test
public void testReader() {
// The reader is initialized and bound to the input data
assertNotNull(reader.read());
}

}

如果您希望步骤范围的持续时间为 执行测试方法。对于更灵活但更具侵入性的方法,您可以使用 这。以下示例计算 中可用的项数 上一示例中显示的读取器:​​StepScopeTestUtils​

int count = StepScopeTestUtils.doInStepScope(stepExecution,
new Callable<Integer>() {
public Integer call() throws Exception {

int count = 0;

while (reader.read() != null) {
count++;
}
return count;
}
});

验证输出文件

当批处理作业写入数据库时,很容易查询数据库以验证 输出符合预期。但是,如果批处理作业写入文件,则它同样 重要提示,必须验证输出。Spring Batch 提供了一个调用的类,用于方便验证输出文件。称为 takes 的方法 两个对象(或两个对象),并逐行断言这两个 文件具有相同的内容。因此,可以创建一个具有预期 输出并将其与实际结果进行比较,如以下示例所示:​​AssertFile​​​​assertFileEquals​​​​File​​​​Resource​

private static final String EXPECTED_FILE = "src/main/resources/data/input.txt";
private static final String OUTPUT_FILE = "target/test-outputs/output.txt";

AssertFile.assertFileEquals(new FileSystemResource(EXPECTED_FILE),
new FileSystemResource(OUTPUT_FILE));

模拟域对象

为 Spring 批处理编写单元和集成测试时遇到的另一个常见问题 组件是如何模拟域对象。一个很好的例子是 ,作为 以下代码片段显示:​​StepExecutionListener​

public class NoWorkFoundStepExecutionListener extends StepExecutionListenerSupport {

public ExitStatus afterStep(StepExecution stepExecution) {
if (stepExecution.getReadCount() == 0) {
return ExitStatus.FAILED;
}
return null;
}
}

该框架提供了前面的侦听器示例,并检查 的读取计数是否为空,从而表示未完成任何工作。虽然这个例子是 相当简单,它用于说明您在以下情况下可能遇到的问题类型 您尝试单元测试类,这些类实现需要 Spring 批处理域的接口 对象。请考虑前面示例中侦听器的以下单元测试:​​StepExecution​

private NoWorkFoundStepExecutionListener tested = new NoWorkFoundStepExecutionListener();

@Test
public void noWork() {
StepExecution stepExecution = new StepExecution("NoProcessingStep",
new JobExecution(new JobInstance(1L, new JobParameters(),
"NoProcessingJob")));

stepExecution.setExitStatus(ExitStatus.COMPLETED);
stepExecution.setReadCount(0);

ExitStatus exitStatus = tested.afterStep(stepExecution);
assertEquals(ExitStatus.FAILED.getExitCode(), exitStatus.getExitCode());
}

由于 Spring Batch 域模型遵循良好的面向对象原则,因此需要 ,这需要 和 才能创建有效的 .虽然这在坚实的领域很好 模型,它确实使为单元测试创建存根对象变得冗长。为了解决这个问题, Spring 批处理测试模块包括一个用于创建域对象的工厂:。给定此工厂,单元测试可以更新为更多 简洁,如以下示例所示:​​StepExecution​​​​JobExecution​​​​JobInstance​​​​JobParameters​​​​StepExecution​​​​MetaDataInstanceFactory​

private NoWorkFoundStepExecutionListener tested = new NoWorkFoundStepExecutionListener();

@Test
public void testAfterStep() {
StepExecution stepExecution = MetaDataInstanceFactory.createStepExecution();

stepExecution.setExitStatus(ExitStatus.COMPLETED);
stepExecution.setReadCount(0);

ExitStatus exitStatus = tested.afterStep(stepExecution);
assertEquals(ExitStatus.FAILED.getExitCode(), exitStatus.getExitCode());
}

前面创建简单的方法只是一种方便的方法 工厂内可用。您可以在其Javadoc中找到完整的方法列表。​​StepExecution​

标签:示例,批处理,Spring,单元测试,StepExecution,Batch,测试,new,public
From: https://blog.51cto.com/u_15326439/5947258

相关文章

  • Spring 5.X系列教程:满足你对Spring5的一切想象-持续更新
    目录​​简介​​​​Spring基础​​​​Core核心技术​​​​Testing测试​​​​DataAccess​​​​WebServlet​​​​WebReactive​​​​总结​​简介是什么让java......
  • Spring Boot 2.X系列教程:七天从无到有掌握Spring Boot-持续更新
    目录​​简介​​​​SpringBoot的基本操作​​​​SpringBoot的构建和部署​​​​SpringBoot工具​​​​SpringBoot的测试​​​​SpringBoot中使用JPA​​​​Spri......
  • IDEA中 maven webapp项目和springboot项目 配置热加载(热交换)1.4Tomcat部署时war和war
    目录​​1、提前说明​​​​1.1、idea汉化​​​​1.2idea的项目类型说明​​​​1.3ideawebapp配置tomcat并启动 ​​​​1.4Tomcat部署时war和warexploded区别​​......
  • 狂神说 spring mvc
    springmvc1、回顾MVC1.1、什么是MVCMVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范。是将业务逻辑、数据、显示分离的方法来组织代码。MVC主......
  • Spring boot controller单元测试
    工具准备测试框架依赖包<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><version>R......
  • Spring Boot + vue-element 开发个人博客项目实战教程(二十一、个人介绍、公告管理、标
    ⭐作者简介:码上言⭐代表教程:​​SpringBoot+vue-element开发个人博客项目实战教程​​⭐专栏内容:零基础学Java、个人博客系统文章目录​​一、个人介绍​​​​二、......
  • Spring REST Docs文档(二)
    自定义请求和响应在某些情况下,您可能不希望完全按照发送的方式记录请求或完全按照收到的响应记录响应。SpringRESTDocs提供了许多预处理器,可用于在记录请求或响应之前对......
  • Spring Batch - 批处理架构
    SpringBatch的设计考虑了可扩展性和不同的最终用户群体。这种分层体系结构突出了三个主要的高级组件:应用程序、核心和基础结构。应用程序包含所有批处理作业和编写的自定......
  • Spring Batch -批处理的域语言
    对于任何有经验的批处理架构师,批处理的总体概念用于春季批次应该是熟悉和舒适的。有“作业”和“步骤”和开发人员提供的处理单元称为和。然而由于Spring模式、操作......
  • Spring Batch -配置和运行作业
    在域部分,整体讨论了体系结构设计,使用下图作为指导:图1.批量构造型虽然这个对象看起来很简单容器的步骤,您必须了解许多配置选项。此外,您必须考虑许多选项如何运行a及其......