/*
* Copyright 2006-2014 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.core.repository.support;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.job.JobSupport;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.batch.core.repository.dao.ExecutionContextDao;
import org.springframework.batch.core.repository.dao.JobExecutionDao;
import org.springframework.batch.core.repository.dao.JobInstanceDao;
import org.springframework.batch.core.repository.dao.StepExecutionDao;
import org.springframework.batch.core.step.StepSupport;
/**
* Test SimpleJobRepository. The majority of test cases are tested using
* EasyMock, however, there were some issues with using it for the stepExecutionDao when
* testing finding or creating steps, so an actual mock class had to be written.
*
* @author Lucas Ward
* @author Will Schipp
*
*/
public class SimpleJobRepositoryTests {
SimpleJobRepository jobRepository;
JobSupport job;
JobParameters jobParameters;
Step stepConfiguration1;
Step stepConfiguration2;
JobExecutionDao jobExecutionDao;
JobInstanceDao jobInstanceDao;
StepExecutionDao stepExecutionDao;
ExecutionContextDao ecDao;
JobInstance jobInstance;
String databaseStep1;
String databaseStep2;
List<String> steps;
JobExecution jobExecution;
@Before
public void setUp() throws Exception {
jobExecutionDao = mock(JobExecutionDao.class);
jobInstanceDao = mock(JobInstanceDao.class);
stepExecutionDao = mock(StepExecutionDao.class);
ecDao = mock(ExecutionContextDao.class);
jobRepository = new SimpleJobRepository(jobInstanceDao, jobExecutionDao, stepExecutionDao, ecDao);
jobParameters = new JobParametersBuilder().addString("bar", "test").toJobParameters();
job = new JobSupport();
job.setBeanName("RepositoryTest");
job.setRestartable(true);
stepConfiguration1 = new StepSupport("TestStep1");
stepConfiguration2 = new StepSupport("TestStep2");
List<Step> stepConfigurations = new ArrayList<Step>();
stepConfigurations.add(stepConfiguration1);
stepConfigurations.add(stepConfiguration2);
job.setSteps(stepConfigurations);
jobInstance = new JobInstance(1L, job.getName());
databaseStep1 = "dbStep1";
databaseStep2 = "dbStep2";
steps = new ArrayList<String>();
steps.add(databaseStep1);
steps.add(databaseStep2);
jobExecution = new JobExecution(new JobInstance(1L, job.getName()), 1L, jobParameters, null);
}
@Test
public void testSaveOrUpdateInvalidJobExecution() {
// failure scenario - must have job ID
JobExecution jobExecution = new JobExecution((JobInstance) null, (JobParameters) null);
try {
jobRepository.update(jobExecution);
fail();
}
catch (Exception ex) {
// expected
}
}
@Test
public void testUpdateValidJobExecution() throws Exception {
JobExecution jobExecution = new JobExecution(new JobInstance(1L, job.getName()), 1L, jobParameters, null);
// new execution - call update on job DAO
jobExecutionDao.updateJobExecution(jobExecution);
jobRepository.update(jobExecution);
assertNotNull(jobExecution.getLastUpdated());
}
@Test
public void testSaveOrUpdateStepExecutionException() {
StepExecution stepExecution = new StepExecution("stepName", null);
// failure scenario -- no step id set.
try {
jobRepository.add(stepExecution);
fail();
}
catch (Exception ex) {
// expected
}
}
@Test
public void testSaveStepExecutionSetsLastUpdated(){
StepExecution stepExecution = new StepExecution("stepName", jobExecution);
long before = System.currentTimeMillis();
jobRepository.add(stepExecution);
assertNotNull(stepExecution.getLastUpdated());
long lastUpdated = stepExecution.getLastUpdated().getTime();
assertTrue(lastUpdated > (before - 1000));
}
@Test
public void testSaveStepExecutions() {
List<StepExecution> stepExecutions = new ArrayList<StepExecution>();
for (int i = 0; i < 3; i++) {
StepExecution stepExecution = new StepExecution("stepName" + i, jobExecution);
stepExecutions.add(stepExecution);
}
jobRepository.addAll(stepExecutions);
verify(stepExecutionDao).saveStepExecutions(stepExecutions);
verify(ecDao).saveExecutionContexts(stepExecutions);
}
@Test(expected = IllegalArgumentException.class)
public void testSaveNullStepExecutions() {
jobRepository.addAll(null);
}
@Test
public void testUpdateStepExecutionSetsLastUpdated(){
StepExecution stepExecution = new StepExecution("stepName", jobExecution);
stepExecution.setId(2343L);
long before = System.currentTimeMillis();
jobRepository.update(stepExecution);
assertNotNull(stepExecution.getLastUpdated());
long lastUpdated = stepExecution.getLastUpdated().getTime();
assertTrue(lastUpdated > (before - 1000));
}
@Test
public void testInterrupted(){
jobExecution.setStatus(BatchStatus.STOPPING);
StepExecution stepExecution = new StepExecution("stepName", jobExecution);
stepExecution.setId(323L);
jobRepository.update(stepExecution);
assertTrue(stepExecution.isTerminateOnly());
}
@Test
public void testIsJobInstanceFalse() throws Exception {
jobInstanceDao.getJobInstance("foo", new JobParameters());
assertFalse(jobRepository.isJobInstanceExists("foo", new JobParameters()));
}
@Test
public void testIsJobInstanceTrue() throws Exception {
when(jobInstanceDao.getJobInstance("foo", new JobParameters())).thenReturn(jobInstance);
jobInstanceDao.getJobInstance("foo", new JobParameters());
assertTrue(jobRepository.isJobInstanceExists("foo", new JobParameters()));
}
@Test(expected = JobExecutionAlreadyRunningException.class)
public void testCreateJobExecutionAlreadyRunning() throws Exception {
jobExecution.setStatus(BatchStatus.STARTED);
jobExecution.setEndTime(null);
when(jobInstanceDao.getJobInstance("foo", new JobParameters())).thenReturn(jobInstance);
when(jobExecutionDao.findJobExecutions(jobInstance)).thenReturn(Arrays.asList(jobExecution));
jobRepository.createJobExecution("foo", new JobParameters());
}
@Test(expected = JobRestartException.class)
public void testCreateJobExecutionStatusUnknown() throws Exception {
jobExecution.setStatus(BatchStatus.UNKNOWN);
jobExecution.setEndTime(new Date());
when(jobInstanceDao.getJobInstance("foo", new JobParameters())).thenReturn(jobInstance);
when(jobExecutionDao.findJobExecutions(jobInstance)).thenReturn(Arrays.asList(jobExecution));
jobRepository.createJobExecution("foo", new JobParameters());
}
@Test(expected = JobInstanceAlreadyCompleteException.class)
public void testCreateJobExecutionAlreadyComplete() throws Exception {
jobExecution.setStatus(BatchStatus.COMPLETED);
jobExecution.setEndTime(new Date());
when(jobInstanceDao.getJobInstance("foo", new JobParameters())).thenReturn(jobInstance);
when(jobExecutionDao.findJobExecutions(jobInstance)).thenReturn(Arrays.asList(jobExecution));
jobRepository.createJobExecution("foo", new JobParameters());
}
}