Reputation: 6690
I have a Junit test for a tasklet, its something like:
@ContextConfiguration(locations = {"/context/job-runner-context.xml"})
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, StepScopeTestExecutionListener.class })
@RunWith(SpringJUnit4ClassRunner.class)
public class InicializaTaskletTest extends BaseTeste {
@Resource
private ChunkContext chunkContext;
@Before
public void setUp() throws Exception {
}
@Test
public void testExecutaTaskletInicializacao() throws Exception {
AtividadesContext atividadesContext = create();
ExecutionContext ctx = chunkContext.getStepContext().getStepExecution().getJobExecution().getExecutionContext();
ctx.put(ATIVIDADES_FOLHA, atividadesContext);
when(service.criarArquivo(diretorio, atividadesContext)).thenReturn(new Emissao();
RepeatStatus retorno = tasklet.execute(mock(StepContribution.class), chunkContext);
}
}
In the tasklet I want to return a emissao object when I call service.criarArquivo with "diretorio" and "atividadesContext" arguments.
The tasklet is something like:
@Value("#{jobExecutionContext['atividadesFolha']}")
private AtividadesContext atividadesContext;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws IOException, AtividadeJaIniciadaException {
EmissaoArquivoSpai emissao = arquivoSpaiService.criarArquivo(diretorioBaseArquivo, atividadesContext);
return RepeatStatus.FINISHED;
}
}
The problem is when I execute junit test the inject of atividadesContext doesn't work or It cannot can be put correctly in the context. And the when clause of test returns a null emissao object, because it's not the arguments the method expect. I can use Mockito.any() to do that, but firstly I want to realize why I cannot inject a context object in a junit test.
When I run the job in normal way it works, I can inject atividadesContext normally.
Upvotes: 0
Views: 3121
Reputation: 21463
In the Spring Batch unit tests, we use a component called the JobSynchronizationManager
(there is the equivalent for the Step as well). Before calling your job scoped bean, you register the JobExecution
with the JobSynchronizationManager
. That makes it available to the ApplicationContext
for wiring purposes.
So looking at your test, you'd structure it like follows:
@Test
public void testExecutaTaskletInicializacao() throws Exception {
AtividadesContext atividadesContext = create();
JobExecution jobExecution = new JobExecution(5l);
ExecutionContext ctx = new ExecutionContext();
ctx.put(ATIVIDADES_FOLHA, atividadesContext);
jobExecution.setExecutionContext(ctx);
JobSynchronizationManager.register(jobExecution);
when(service.criarArquivo(diretorio, atividadesContext)).thenReturn(new Emissao());
RepeatStatus retorno = tasklet.execute(mock(StepContribution.class), chunkContext);
JobSynchronizationManager.release();
}
You can read more about the JobSynchronizationManager
in the documentation here: http://docs.spring.io/spring-batch/trunk/apidocs/org/springframework/batch/core/scope/context/JobSynchronizationManager.html
Upvotes: 2