From 2fcaafd9fd1f2ce9e0362a21ad3ae6b680f7ff03 Mon Sep 17 00:00:00 2001 From: Mahmoud Ben Hassine Date: Thu, 17 May 2018 13:31:41 +0200 Subject: [PATCH] Add a new annotation `@SpringBatchTest` to simplify testing This commit adds a new annotation `@SpringBatchTest` that: * configures two beans `JobLauncherTestUtils` and `JobRepositoryTestUtils` in the test context. * imports the `StepScopeTestExecutionListener` and `JobScopeTestExecutionListener` as test execution listeners. Resolves BATCH-2718 --- build.gradle | 1 + spring-batch-docs/asciidoc/testing.adoc | 56 ++++++- .../batch/test/JobRepositoryTestUtils.java | 6 +- .../context/BatchTestContextCustomizer.java | 54 +++++++ .../BatchTestContextCustomizerFactory.java | 42 +++++ .../batch/test/context/SpringBatchTest.java | 98 ++++++++++++ .../main/resources/META-INF/spring.factories | 4 + .../batch/test/SpringBatchTestTests.java | 150 ++++++++++++++++++ ...BatchTestContextCustomizerFactoryTest.java | 68 ++++++++ .../BatchTestContextCustomizerTest.java | 66 ++++++++ 10 files changed, 536 insertions(+), 9 deletions(-) create mode 100644 spring-batch-test/src/main/java/org/springframework/batch/test/context/BatchTestContextCustomizer.java create mode 100644 spring-batch-test/src/main/java/org/springframework/batch/test/context/BatchTestContextCustomizerFactory.java create mode 100644 spring-batch-test/src/main/java/org/springframework/batch/test/context/SpringBatchTest.java create mode 100644 spring-batch-test/src/main/resources/META-INF/spring.factories create mode 100644 spring-batch-test/src/test/java/org/springframework/batch/test/SpringBatchTestTests.java create mode 100644 spring-batch-test/src/test/java/org/springframework/batch/test/context/BatchTestContextCustomizerFactoryTest.java create mode 100644 spring-batch-test/src/test/java/org/springframework/batch/test/context/BatchTestContextCustomizerTest.java diff --git a/build.gradle b/build.gradle index b0e139713c..2b1b11a7cb 100644 --- a/build.gradle +++ b/build.gradle @@ -497,6 +497,7 @@ project('spring-batch-test') { testCompile "org.apache.commons:commons-dbcp2:$commonsDdbcpVersion" testCompile "org.hsqldb:hsqldb:$hsqldbVersion" + testCompile "org.mockito:mockito-core:$mockitoVersion" optional "org.aspectj:aspectjrt:$aspectjVersion" optional "javax.batch:javax.batch-api:$javaxBatchApiVersion" diff --git a/spring-batch-docs/asciidoc/testing.adoc b/spring-batch-docs/asciidoc/testing.adoc index 110ea973c3..6327dee9c6 100644 --- a/spring-batch-docs/asciidoc/testing.adoc +++ b/spring-batch-docs/asciidoc/testing.adoc @@ -28,19 +28,24 @@ In order for the unit test to run a batch job, the framework must this behavior: -* `@RunWith(SpringJUnit4ClassRunner.class)`: +* `@RunWith(SpringRunner.class)`: Indicates that the class should use Spring's JUnit facilities * `@ContextConfiguration(...)`: Indicates which resources to configure the `ApplicationContext` with. -The following example shows the two annotations in use: +Starting from v4.1, it is also possible to inject Spring Batch test utilities +like the `JobLauncherTestUtils` and `JobRepositoryTestUtils` in the test context +using the `@SpringBatchTest` annotation. + +The following example shows the annotations in use: .Using Java Configuration [source, java, role="javaContent"] ---- -@RunWith(SpringJUnit4ClassRunner.class) +@SpringBatchTest +@RunWith(SpringRunner.class) @ContextConfiguration(classes=SkipSampleConfiguration.class) public class SkipSampleFunctionalTests { ... } ---- @@ -48,7 +53,8 @@ public class SkipSampleFunctionalTests { ... } .Using XML Configuration [source, java, role="xmlContent"] ---- -@RunWith(SpringJUnit4ClassRunner.class) +@SpringBatchTest +@RunWith(SpringRunner.class) @ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/skipSampleJob.xml" }) public class SkipSampleFunctionalTests { ... } @@ -81,7 +87,8 @@ In the following example, the batch job reads from the database and .XML Based Configuration [source, java, role="xmlContent"] ---- -@RunWith(SpringJUnit4ClassRunner.class) +@SpringBatchTest +@RunWith(SpringRunner.class) @ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/skipSampleJob.xml" }) public class SkipSampleFunctionalTests { @@ -115,7 +122,8 @@ public class SkipSampleFunctionalTests { .Java Based Configuration [source, java, role="javaContent"] ---- -@RunWith(SpringJUnit4ClassRunner.class) +@SpringBatchTest +@RunWith(SpringRunner.class) @ContextConfiguration(classes=SkipSampleConfiguration.class) public class SkipSampleFunctionalTests { @@ -187,7 +195,7 @@ The listener is declared at the class level, and its job is to @ContextConfiguration @TestExecutionListeners( { DependencyInjectionTestExecutionListener.class, StepScopeTestExecutionListener.class }) -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) public class StepScopeTestExecutionListenerIntegrationTests { // This component is defined step-scoped, so it cannot be injected unless @@ -195,7 +203,7 @@ public class StepScopeTestExecutionListenerIntegrationTests { @Autowired private ItemReader reader; - public StepExecution getStepExection() { + public StepExecution getStepExecution() { StepExecution execution = MetaDataInstanceFactory.createStepExecution(); execution.getExecutionContext().putString("input.data", "foo,bar,spam"); return execution; @@ -222,6 +230,38 @@ There are two `TestExecutionListeners`. One `StepExecution`). If a factory method is not provided, then a default `StepExecution` is created. +Starting from v4.1, the `StepScopeTestExecutionListener` and + `JobScopeTestExecutionListener` are imported as test execution listeners + if the test class is annotated with `@SpringBatchTest`. The preceding test + example can be configured as follows: + +[source, java] +---- +@SpringBatchTest +@RunWith(SpringRunner.class) +@ContextConfiguration +public class StepScopeTestExecutionListenerIntegrationTests { + + // This component is defined step-scoped, so it cannot be injected unless + // a step is active... + @Autowired + private ItemReader 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()); + } + +} +---- + The listener approach is convenient if you want the duration of the step scope to be the execution of the test method. For a more flexible but more invasive approach, you can use the diff --git a/spring-batch-test/src/main/java/org/springframework/batch/test/JobRepositoryTestUtils.java b/spring-batch-test/src/main/java/org/springframework/batch/test/JobRepositoryTestUtils.java index 146302a491..0cf3c7fcd8 100644 --- a/spring-batch-test/src/main/java/org/springframework/batch/test/JobRepositoryTestUtils.java +++ b/spring-batch-test/src/main/java/org/springframework/batch/test/JobRepositoryTestUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2007 the original author or authors. + * Copyright 2006-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +36,7 @@ import org.springframework.batch.core.repository.JobRestartException; import org.springframework.batch.core.repository.dao.AbstractJdbcBatchMetadataDao; import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcOperations; import org.springframework.jdbc.core.JdbcTemplate; @@ -49,6 +50,7 @@ * the transaction. * * @author Dave Syer + * @author Mahmoud Ben Hassine */ public class JobRepositoryTestUtils extends AbstractJdbcBatchMetadataDao implements InitializingBean { @@ -95,6 +97,7 @@ public JobRepositoryTestUtils(JobRepository jobRepository, DataSource dataSource setDataSource(dataSource); } + @Autowired public final void setDataSource(DataSource dataSource) { jdbcTemplate = new JdbcTemplate(dataSource); } @@ -109,6 +112,7 @@ public void setJobParametersIncrementer(JobParametersIncrementer jobParametersIn /** * @param jobRepository the jobRepository to set */ + @Autowired public void setJobRepository(JobRepository jobRepository) { this.jobRepository = jobRepository; } diff --git a/spring-batch-test/src/main/java/org/springframework/batch/test/context/BatchTestContextCustomizer.java b/spring-batch-test/src/main/java/org/springframework/batch/test/context/BatchTestContextCustomizer.java new file mode 100644 index 0000000000..c2933cec38 --- /dev/null +++ b/spring-batch-test/src/main/java/org/springframework/batch/test/context/BatchTestContextCustomizer.java @@ -0,0 +1,54 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.test.context; + +import org.springframework.batch.test.JobLauncherTestUtils; +import org.springframework.batch.test.JobRepositoryTestUtils; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.test.context.ContextCustomizer; +import org.springframework.test.context.MergedContextConfiguration; +import org.springframework.util.Assert; + +/** + * {@link ContextCustomizer} implementation that adds batch test utility classes + * ({@link JobLauncherTestUtils} and {@link JobRepositoryTestUtils}) as beans in + * the test context. + * + * @author Mahmoud Ben Hassine + * @since 4.1 + */ +public class BatchTestContextCustomizer implements ContextCustomizer { + + private static final String JOB_LAUNCHER_TEST_UTILS_BEAN_NAME = "jobLauncherTestUtils"; + private static final String JOB_REPOSITORY_TEST_UTILS_BEAN_NAME = "jobRepositoryTestUtils"; + + @Override + public void customizeContext(ConfigurableApplicationContext context, MergedContextConfiguration mergedConfig) { + ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); + Assert.isInstanceOf(BeanDefinitionRegistry.class, beanFactory, + "The bean factory must be an instance of BeanDefinitionRegistry"); + BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; + + registry.registerBeanDefinition(JOB_LAUNCHER_TEST_UTILS_BEAN_NAME, + new RootBeanDefinition(JobLauncherTestUtils.class)); + registry.registerBeanDefinition(JOB_REPOSITORY_TEST_UTILS_BEAN_NAME, + new RootBeanDefinition(JobRepositoryTestUtils.class)); + } + +} diff --git a/spring-batch-test/src/main/java/org/springframework/batch/test/context/BatchTestContextCustomizerFactory.java b/spring-batch-test/src/main/java/org/springframework/batch/test/context/BatchTestContextCustomizerFactory.java new file mode 100644 index 0000000000..645ca5b373 --- /dev/null +++ b/spring-batch-test/src/main/java/org/springframework/batch/test/context/BatchTestContextCustomizerFactory.java @@ -0,0 +1,42 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.test.context; + +import java.util.List; + +import org.springframework.core.annotation.AnnotatedElementUtils; +import org.springframework.test.context.ContextConfigurationAttributes; +import org.springframework.test.context.ContextCustomizer; +import org.springframework.test.context.ContextCustomizerFactory; + +/** + * Factory for {@link BatchTestContextCustomizer}. + * + * @author Mahmoud Ben Hassine + * @since 4.1 + */ +public class BatchTestContextCustomizerFactory implements ContextCustomizerFactory { + + @Override + public ContextCustomizer createContextCustomizer(Class testClass, List configAttributes) { + SpringBatchTest springBatchTest = AnnotatedElementUtils.findMergedAnnotation(testClass, SpringBatchTest.class); + if (springBatchTest != null) { + return new BatchTestContextCustomizer(); + } + return null; + } + +} diff --git a/spring-batch-test/src/main/java/org/springframework/batch/test/context/SpringBatchTest.java b/spring-batch-test/src/main/java/org/springframework/batch/test/context/SpringBatchTest.java new file mode 100644 index 0000000000..e9c1bffcf4 --- /dev/null +++ b/spring-batch-test/src/main/java/org/springframework/batch/test/context/SpringBatchTest.java @@ -0,0 +1,98 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.test.context; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.batch.test.JobLauncherTestUtils; +import org.springframework.batch.test.JobRepositoryTestUtils; +import org.springframework.batch.test.JobScopeTestExecutionListener; +import org.springframework.batch.test.StepScopeTestExecutionListener; +import org.springframework.test.context.TestExecutionListeners; + +/** + * Annotation that can be specified on a test class that runs Spring Batch based tests. + * Provides the following features over the regular Spring TestContext Framework: + *
    + *
  • Registers a {@link JobLauncherTestUtils} bean with the + * {@link BatchTestContextCustomizer#JOB_LAUNCHER_TEST_UTILS_BEAN_NAME} which can be used + * in tests for launching jobs and steps. + *
  • + *
  • Registers a {@link JobRepositoryTestUtils} bean + * with the {@link BatchTestContextCustomizer#JOB_REPOSITORY_TEST_UTILS_BEAN_NAME} + * which can be used in tests setup to create or remove job executions. + *
  • + *
  • Registers the {@link StepScopeTestExecutionListener} and {@link JobScopeTestExecutionListener} + * as test execution listeners which are required to test step/job scoped beans. + *
  • + *
+ *

+ * A typical usage of this annotation is like: + * + *

+ * @RunWith(SpringRunner.class)
+ * @SpringBatchTest
+ * @ContextConfiguration(classes = MyBatchJobConfiguration.class)
+ * public class MyBatchJobTests {
+ *
+ *    @@Autowired
+ *    private JobLauncherTestUtils jobLauncherTestUtils;
+ *
+ *    @@Autowired
+ *    private JobRepositoryTestUtils jobRepositoryTestUtils;
+ *
+ *    @Before
+ *    public void clearJobExecutions() {
+ *       this.jobRepositoryTestUtils.removeJobExecutions();
+ *    }
+ *
+ *    @Test
+ *    public void testMyJob() throws Exception {
+ *       // given
+ *       JobParameters jobParameters = this.jobLauncherTestUtils.getUniqueJobParameters();
+ *
+ *       // when
+ *       JobExecution jobExecution = this.jobLauncherTestUtils.launchJob(jobParameters);
+ *
+ *       // then
+ *       Assert.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
+ *    }
+ *
+ * }
+ * 
+ * + * @author Mahmoud Ben Hassine + * @since 4.1 + * @see JobLauncherTestUtils + * @see JobRepositoryTestUtils + * @see StepScopeTestExecutionListener + * @see JobScopeTestExecutionListener + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@TestExecutionListeners( + listeners = {StepScopeTestExecutionListener.class, JobScopeTestExecutionListener.class}, + mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS +) +public @interface SpringBatchTest { +} diff --git a/spring-batch-test/src/main/resources/META-INF/spring.factories b/spring-batch-test/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000000..98e6e569c6 --- /dev/null +++ b/spring-batch-test/src/main/resources/META-INF/spring.factories @@ -0,0 +1,4 @@ +# Batch ContextCustomizerFactory implementation for the Spring TestContext Framework +# +org.springframework.test.context.ContextCustomizerFactory= \ +org.springframework.batch.test.context.BatchTestContextCustomizerFactory diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/SpringBatchTestTests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/SpringBatchTestTests.java new file mode 100644 index 0000000000..497ec59df4 --- /dev/null +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/SpringBatchTestTests.java @@ -0,0 +1,150 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.test; + +import java.util.Arrays; +import javax.sql.DataSource; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; +import org.springframework.batch.core.configuration.annotation.JobScope; +import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; +import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.support.ListItemReader; +import org.springframework.batch.repeat.RepeatStatus; +import org.springframework.batch.test.context.SpringBatchTest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * Test cases for usage of {@link SpringBatchTest} annotation. + * + * @author Mahmoud Ben Hassine + */ +@RunWith(SpringRunner.class) +@SpringBatchTest +@ContextConfiguration(classes = SpringBatchTestTests.JobConfiguration.class) +public class SpringBatchTestTests { + + @Autowired + private JobLauncherTestUtils jobLauncherTestUtils; + + @Autowired + private JobRepositoryTestUtils jobRepositoryTestUtils; + + @Autowired + private ItemReader stepScopedItemReader; + + @Autowired + private ItemReader jobScopedItemReader; + + @Before + public void setUp() { + this.jobRepositoryTestUtils.removeJobExecutions(); + } + + public StepExecution getStepExecution() { + StepExecution execution = MetaDataInstanceFactory.createStepExecution(); + execution.getExecutionContext().putString("input.data", "foo,bar"); + return execution; + } + + public JobExecution getJobExecution() { + JobExecution execution = MetaDataInstanceFactory.createJobExecution(); + execution.getExecutionContext().putString("input.data", "foo,bar"); + return execution; + } + + @Test + public void testStepScopedItemReader() throws Exception { + Assert.assertEquals("foo", this.stepScopedItemReader.read()); + Assert.assertEquals("bar", this.stepScopedItemReader.read()); + Assert.assertNull(this.stepScopedItemReader.read()); + } + + @Test + public void testJobScopedItemReader() throws Exception { + Assert.assertEquals("foo", this.jobScopedItemReader.read()); + Assert.assertEquals("bar", this.jobScopedItemReader.read()); + Assert.assertNull(this.jobScopedItemReader.read()); + } + + @Test + public void testJob() throws Exception { + // when + JobExecution jobExecution = this.jobLauncherTestUtils.launchJob(); + + // then + Assert.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); + } + + @Configuration + @EnableBatchProcessing + public static class JobConfiguration { + + @Autowired + private JobBuilderFactory jobBuilderFactory; + + @Autowired + private StepBuilderFactory stepBuilderFactory; + + @Bean + public DataSource dataSource() { + return new EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.HSQL) + .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb.sql") + .build(); + } + + @Bean + @StepScope + public ItemReader stepScopedItemReader(@Value("#{stepExecutionContext['input.data']}") String data) { + return new ListItemReader<>(Arrays.asList(data.split(","))); + } + + @Bean + @JobScope + public ItemReader jobScopedItemReader(@Value("#{jobExecutionContext['input.data']}") String data) { + return new ListItemReader<>(Arrays.asList(data.split(","))); + } + + @Bean + public Job job() { + return this.jobBuilderFactory.get("job") + .start(this.stepBuilderFactory.get("step") + .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) + .build()) + .build(); + } + } +} diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/context/BatchTestContextCustomizerFactoryTest.java b/spring-batch-test/src/test/java/org/springframework/batch/test/context/BatchTestContextCustomizerFactoryTest.java new file mode 100644 index 0000000000..acb100a4cc --- /dev/null +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/context/BatchTestContextCustomizerFactoryTest.java @@ -0,0 +1,68 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.test.context; + +import java.util.Collections; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +import org.springframework.test.context.ContextConfigurationAttributes; +import org.springframework.test.context.ContextCustomizer; + +/** + * @author Mahmoud Ben Hassine + */ +public class BatchTestContextCustomizerFactoryTest { + + private BatchTestContextCustomizerFactory factory = new BatchTestContextCustomizerFactory(); + + @Test + public void testCreateContextCustomizer_whenAnnotationIsPresent() { + // given + Class testClass = MyJobTest.class; + List configAttributes = Collections.emptyList(); + + // when + ContextCustomizer contextCustomizer = this.factory.createContextCustomizer(testClass, configAttributes); + + // then + Assert.assertNotNull(contextCustomizer); + } + + @Test + public void testCreateContextCustomizer_whenAnnotationIsAbsent() { + // given + Class testClass = MyOtherJobTest.class; + List configAttributes = Collections.emptyList(); + + // when + ContextCustomizer contextCustomizer = this.factory.createContextCustomizer(testClass, configAttributes); + + // then + Assert.assertNull(contextCustomizer); + } + + @SpringBatchTest + private static class MyJobTest { + + } + + private static class MyOtherJobTest { + + } +} diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/context/BatchTestContextCustomizerTest.java b/spring-batch-test/src/test/java/org/springframework/batch/test/context/BatchTestContextCustomizerTest.java new file mode 100644 index 0000000000..178cf41f5a --- /dev/null +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/context/BatchTestContextCustomizerTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.test.context; + +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.mockito.Mockito; + +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.test.context.MergedContextConfiguration; + +/** + * @author Mahmoud Ben Hassine + */ +public class BatchTestContextCustomizerTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private BatchTestContextCustomizer contextCustomizer = new BatchTestContextCustomizer(); + + @Test + public void testCustomizeContext() { + // given + ConfigurableApplicationContext context = new GenericApplicationContext(); + MergedContextConfiguration mergedConfig = Mockito.mock(MergedContextConfiguration.class); + + // when + this.contextCustomizer.customizeContext(context, mergedConfig); + + // then + Assert.assertTrue(context.containsBean("jobLauncherTestUtils")); + Assert.assertTrue(context.containsBean("jobRepositoryTestUtils")); + } + + @Test + public void testCustomizeContext_whenBeanFactoryIsNotAnInstanceOfBeanDefinitionRegistry() { + // given + ConfigurableApplicationContext context = Mockito.mock(ConfigurableApplicationContext.class); + MergedContextConfiguration mergedConfig = Mockito.mock(MergedContextConfiguration.class); + this.expectedException.expect(IllegalArgumentException.class); + this.expectedException.expectMessage("The bean factory must be an instance of BeanDefinitionRegistry"); + + // when + this.contextCustomizer.customizeContext(context, mergedConfig); + + // then + // expected exception + } +}