Files
spring-batch/build/reference-epub-work/ch10s04.xhtml
Michael Minella 75ab909314 update
2017-03-23 10:18:33 -05:00

56 lines
3.7 KiB
HTML

<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:pls="http://www.w3.org/2005/01/pronunciation-lexicon" xmlns:ssml="http://www.w3.org/2001/10/synthesis" xmlns:svg="http://www.w3.org/2000/svg"><head><title>Testing Step-Scoped Components</title><link rel="stylesheet" type="text/css" href="docbook-epub.css"/><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"/><link rel="prev" href="ch10s03.xhtml" title="Testing Individual Steps"/><link rel="next" href="ch10s05.xhtml" title="Validating Output Files"/></head><body><header/><section class="section" title="Testing Step-Scoped Components" epub:type="subchapter" id="d5e3514"><div class="titlepage"><div><div><h2 class="title" style="clear: both">Testing Step-Scoped Components</h2></div></div></div><p>Often the components that are configured for your steps at runtime
use step scope and late binding to inject context from the step or job
execution. These are tricky to test as standalone components unless you
have a way to set the context as if they were in a step execution. That is
the goal of two components in Spring Batch: the
<code class="classname">StepScopeTestExecutionListener</code> and the
<code class="classname">StepScopeTestUtils</code>.</p><p>The listener is declared at the class level, and its job is to
create a step execution context for each test method. For example:</p><pre class="programlisting">@ContextConfiguration
@TestExecutionListeners( { DependencyInjectionTestExecutionListener.class,
StepScopeTestExecutionListener.class })
@RunWith(SpringJUnit4ClassRunner.class)
public class StepScopeTestExecutionListenerIntegrationTests {
// This component is defined step-scoped, so it cannot be injected unless
// a step is active...
@Autowired
private ItemReader&lt;String&gt; reader;
public StepExecution getStepExection() {
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());
}
}</pre><p>There are two <code class="classname">TestExecutionListeners</code>, one
from the regular Spring Test framework and handles dependency injection
from the configured application context, injecting the reader, and the
other is the Spring Batch
<code class="classname">StepScopeTestExecutionListener</code>. It works by looking
for a factory method in the test case for a
<code class="classname">StepExecution</code>, and using that as the context for
the test method, as if that execution was active in a Step at runtime. The
factory method is detected by its signature (it just has to return a
<code class="classname">StepExecution</code>). If a factory method is not provided
then a default <code class="classname">StepExecution</code> is created.</p><p>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
<code class="classname">StepScopeTestUtils</code>. For example, to count the
number of items available in the reader above:</p><pre class="programlisting">int count = StepScopeTestUtils.doInStepScope(stepExecution,
new Callable&lt;Integer&gt;() {
public Integer call() throws Exception {
int count = 0;
while (reader.read() != null) {
count++;
}
return count;
}
});</pre></section><footer/></body></html>