Skip to content

Commit fe51fde

Browse files
authored
Meta-annotate @SpringBatchTest with @ExtendWith(SpringExtension.class)
Resolves #3647
1 parent 60a99ca commit fe51fde

File tree

4 files changed

+194
-6
lines changed

4 files changed

+194
-6
lines changed

build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ allprojects {
8585
jettisonVersion = '1.2' //? => upgrade to 1.4 and the build fails (deprecated anyway via xstream)
8686
jmsVersion = '2.0.1'
8787
junitVersion = '4.13'
88+
junitJupiterVersion = '5.6.2'
8889
log4jVersion = '2.13.0'
8990
mysqlVersion = '8.0.18'
9091
mockitoVersion = '3.1.0'
@@ -515,8 +516,11 @@ project('spring-batch-test') {
515516
testCompile "org.hsqldb:hsqldb:$hsqldbVersion"
516517
testCompile "org.mockito:mockito-core:$mockitoVersion"
517518

519+
testRuntime "org.junit.jupiter:junit-jupiter-engine:$junitJupiterVersion"
520+
518521
optional "org.aspectj:aspectjrt:$aspectjVersion"
519522
optional "javax.batch:javax.batch-api:$javaxBatchApiVersion"
523+
optional "org.junit.jupiter:junit-jupiter-api:$junitJupiterVersion"
520524
}
521525
}
522526

spring-batch-test/src/main/java/org/springframework/batch/test/context/SpringBatchTest.java

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2018 the original author or authors.
2+
* Copyright 2018-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,11 +22,14 @@
2222
import java.lang.annotation.RetentionPolicy;
2323
import java.lang.annotation.Target;
2424

25+
import org.junit.jupiter.api.extension.ExtendWith;
26+
2527
import org.springframework.batch.test.JobLauncherTestUtils;
2628
import org.springframework.batch.test.JobRepositoryTestUtils;
2729
import org.springframework.batch.test.JobScopeTestExecutionListener;
2830
import org.springframework.batch.test.StepScopeTestExecutionListener;
2931
import org.springframework.test.context.TestExecutionListeners;
32+
import org.springframework.test.context.junit.jupiter.SpringExtension;
3033

3134
/**
3235
* Annotation that can be specified on a test class that runs Spring Batch based tests.
@@ -45,7 +48,7 @@
4548
* </li>
4649
* </ul>
4750
* <p>
48-
* A typical usage of this annotation is like:
51+
* A typical usage of this annotation with JUnit 4 is like:
4952
*
5053
* <pre class="code">
5154
* &#064;RunWith(SpringRunner.class)
@@ -79,6 +82,40 @@
7982
* }
8083
* </pre>
8184
*
85+
* For JUnit 5, this annotation can be used without having to manually register the
86+
* {@link SpringExtension} since {@code @SpringBatchTest} is meta-annotated with
87+
* {@code @ExtendWith(SpringExtension.class)}:
88+
*
89+
* <pre class="code">
90+
* &#064;SpringBatchTest
91+
* &#064;ContextConfiguration(classes = MyBatchJobConfiguration.class)
92+
* public class MyBatchJobTests {
93+
*
94+
* &#064;@Autowired
95+
* private JobLauncherTestUtils jobLauncherTestUtils;
96+
*
97+
* &#064;@Autowired
98+
* private JobRepositoryTestUtils jobRepositoryTestUtils;
99+
*
100+
* &#064;BeforeEach
101+
* public void clearJobExecutions() {
102+
* this.jobRepositoryTestUtils.removeJobExecutions();
103+
* }
104+
*
105+
* &#064;Test
106+
* public void testMyJob() throws Exception {
107+
* // given
108+
* JobParameters jobParameters = this.jobLauncherTestUtils.getUniqueJobParameters();
109+
*
110+
* // when
111+
* JobExecution jobExecution = this.jobLauncherTestUtils.launchJob(jobParameters);
112+
*
113+
* // then
114+
* Assertions.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
115+
* }
116+
*
117+
* }
118+
* </pre>
82119
* @author Mahmoud Ben Hassine
83120
* @since 4.1
84121
* @see JobLauncherTestUtils
@@ -94,5 +131,6 @@
94131
listeners = {StepScopeTestExecutionListener.class, JobScopeTestExecutionListener.class},
95132
mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS
96133
)
134+
@ExtendWith(SpringExtension.class)
97135
public @interface SpringBatchTest {
98136
}

spring-batch-test/src/test/java/org/springframework/batch/test/SpringBatchTestTests.java renamed to spring-batch-test/src/test/java/org/springframework/batch/test/SpringBatchTestJUnit4Tests.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2018 the original author or authors.
2+
* Copyright 2018-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -46,14 +46,14 @@
4646
import org.springframework.test.context.junit4.SpringRunner;
4747

4848
/**
49-
* Test cases for usage of {@link SpringBatchTest} annotation.
49+
* Test cases for usage of {@link SpringBatchTest} annotation with JUnit 4.
5050
*
5151
* @author Mahmoud Ben Hassine
5252
*/
5353
@RunWith(SpringRunner.class)
5454
@SpringBatchTest
55-
@ContextConfiguration(classes = SpringBatchTestTests.JobConfiguration.class)
56-
public class SpringBatchTestTests {
55+
@ContextConfiguration
56+
public class SpringBatchTestJUnit4Tests {
5757

5858
@Autowired
5959
private JobLauncherTestUtils jobLauncherTestUtils;
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
/*
2+
* Copyright 2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.batch.test;
17+
18+
import java.util.Arrays;
19+
20+
import javax.sql.DataSource;
21+
22+
import org.junit.jupiter.api.Assertions;
23+
import org.junit.jupiter.api.BeforeEach;
24+
import org.junit.jupiter.api.Test;
25+
26+
import org.springframework.batch.core.ExitStatus;
27+
import org.springframework.batch.core.Job;
28+
import org.springframework.batch.core.JobExecution;
29+
import org.springframework.batch.core.JobParameters;
30+
import org.springframework.batch.core.StepExecution;
31+
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
32+
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
33+
import org.springframework.batch.core.configuration.annotation.JobScope;
34+
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
35+
import org.springframework.batch.core.configuration.annotation.StepScope;
36+
import org.springframework.batch.item.ItemReader;
37+
import org.springframework.batch.item.support.ListItemReader;
38+
import org.springframework.batch.repeat.RepeatStatus;
39+
import org.springframework.batch.test.context.SpringBatchTest;
40+
import org.springframework.beans.factory.annotation.Autowired;
41+
import org.springframework.beans.factory.annotation.Value;
42+
import org.springframework.context.annotation.Bean;
43+
import org.springframework.context.annotation.Configuration;
44+
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
45+
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
46+
import org.springframework.test.context.ContextConfiguration;
47+
48+
/**
49+
* Test cases for usage of {@link SpringBatchTest} annotation with JUnit 5.
50+
*
51+
* @author Mahmoud Ben Hassine
52+
*/
53+
@SpringBatchTest
54+
@ContextConfiguration
55+
public class SpringBatchTestJUnit5Tests {
56+
57+
@Autowired
58+
private JobLauncherTestUtils jobLauncherTestUtils;
59+
60+
@Autowired
61+
private JobRepositoryTestUtils jobRepositoryTestUtils;
62+
63+
@Autowired
64+
private ItemReader<String> stepScopedItemReader;
65+
66+
@Autowired
67+
private ItemReader<String> jobScopedItemReader;
68+
69+
@BeforeEach
70+
public void setUp() {
71+
this.jobRepositoryTestUtils.removeJobExecutions();
72+
}
73+
74+
@Test
75+
public void testStepScopedItemReader() throws Exception {
76+
Assertions.assertEquals("foo", this.stepScopedItemReader.read());
77+
Assertions.assertEquals("bar", this.stepScopedItemReader.read());
78+
Assertions.assertNull(this.stepScopedItemReader.read());
79+
}
80+
81+
@Test
82+
public void testJobScopedItemReader() throws Exception {
83+
Assertions.assertEquals("foo", this.jobScopedItemReader.read());
84+
Assertions.assertEquals("bar", this.jobScopedItemReader.read());
85+
Assertions.assertNull(this.jobScopedItemReader.read());
86+
}
87+
88+
@Test
89+
public void testJob() throws Exception {
90+
// given
91+
JobParameters jobParameters = this.jobLauncherTestUtils.getUniqueJobParameters();
92+
93+
// when
94+
JobExecution jobExecution = this.jobLauncherTestUtils.launchJob(jobParameters);
95+
96+
// then
97+
Assertions.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
98+
}
99+
100+
public StepExecution getStepExecution() {
101+
StepExecution execution = MetaDataInstanceFactory.createStepExecution();
102+
execution.getExecutionContext().putString("input.data", "foo,bar");
103+
return execution;
104+
}
105+
106+
public JobExecution getJobExecution() {
107+
JobExecution execution = MetaDataInstanceFactory.createJobExecution();
108+
execution.getExecutionContext().putString("input.data", "foo,bar");
109+
return execution;
110+
}
111+
112+
@Configuration
113+
@EnableBatchProcessing
114+
public static class JobConfiguration {
115+
116+
@Bean
117+
public DataSource dataSource() {
118+
return new EmbeddedDatabaseBuilder()
119+
.setType(EmbeddedDatabaseType.HSQL)
120+
.addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql")
121+
.addScript("/org/springframework/batch/core/schema-hsqldb.sql")
122+
.build();
123+
}
124+
125+
@Bean
126+
@StepScope
127+
public ItemReader<String> stepScopedItemReader(@Value("#{stepExecutionContext['input.data']}") String data) {
128+
return new ListItemReader<>(Arrays.asList(data.split(",")));
129+
}
130+
131+
@Bean
132+
@JobScope
133+
public ItemReader<String> jobScopedItemReader(@Value("#{jobExecutionContext['input.data']}") String data) {
134+
return new ListItemReader<>(Arrays.asList(data.split(",")));
135+
}
136+
137+
@Bean
138+
public Job job(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory) {
139+
return jobBuilderFactory.get("job")
140+
.start(stepBuilderFactory.get("step")
141+
.tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED)
142+
.build())
143+
.build();
144+
}
145+
}
146+
}

0 commit comments

Comments
 (0)