diff --git a/src/site/docbook/reference/testing.xml b/src/site/docbook/reference/testing.xml index 1312e35d7..43e1a8d76 100644 --- a/src/site/docbook/reference/testing.xml +++ b/src/site/docbook/reference/testing.xml @@ -131,4 +131,91 @@ + +
+ Mocking Domain Objects + + Another common issue encountered while writing unit and integration + tests for Spring Batch components is how to mock domain objects. A good + example is a StepExecutionListener, as illustrated + below: + + + public class NoWorkFoundStepExecutionListener extends StepExecutionListenerSupport { + + public ExitStatus afterStep(StepExecution stepExecution) { + if (stepExecution.getReadCount() == 0) { + throw new NoWorkFoundException("Step has not processed any items"); + } + return stepExecution.getExitStatus(); + } + } + + + + The above listener is provided by the framework and checks a + StepExecution for an empty read count, thus + signifying that no work was done. While this example is fairly simple, it + serves to illustrate the types of problems that may be encountered when + attempting to unit test classes that implement interfaces requiring Spring + Batch domain objects. Consider the above listener's unit test: + + + private NoWorkFoundStepExecutionListener tested = new NoWorkFoundStepExecutionListener(); + + @Test + public void testAfterStep() { + StepExecution stepExecution = new StepExecution("NoProcessingStep", + new JobExecution( + new JobInstance(1L, new JobParameters(), "NoProcessingJob"))); + + stepExecution.setReadCount(0); + + try { + tested.afterStep(stepExecution); + fail(); + } catch (NoWorkFoundException e) { + assertEquals("Step has not processed any items", e.getMessage()); + } + } + + + + Because the Spring Batch domain model follows good object orientated + principles, the StepExecution requires a + JobExecution, which requires a + JobInstance and + JobParameters in order to create a valid + StepExecution. While this is good in a solid domain + model, it does make creating stub objects for unit testing verbose. To + address this issue, the Spring Batch test module includes a factory for + creating domain objects: MetaDataInstanceFactory. + Given this factory, the unit test can be updated to be more concise: + + + + private NoWorkFoundStepExecutionListener tested = new NoWorkFoundStepExecutionListener(); + + @Test + public void testAfterStep() { + StepExecution stepExecution = MetaDataInstanceFactory.createStepExecution(); + + stepExecution.setReadCount(0); + + try { + tested.afterStep(stepExecution); + fail(); + } catch (NoWorkFoundException e) { + assertEquals("Step has not processed any items", e.getMessage()); + } + } + + + + The above method for creating a simple + StepExecution is just one convenience method + available within the factory. A full method listing can be found in its + Javadoc. +