alexpfx
alexpfx

Reputation: 6690

Retrieve context value within a Junit Test.

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

Answers (1)

Michael Minella
Michael Minella

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

Related Questions