org.activiti.engine.test.ActivitiRule Maven / Gradle / Ivy
/* 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.activiti.engine.test;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.FormService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.ManagementService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.test.TestHelper;
import org.activiti.engine.test.mock.ActivitiMockSupport;
import org.junit.internal.AssumptionViolatedException;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.runners.model.MultipleFailureException;
import org.junit.runners.model.Statement;
/**
* Convenience for ProcessEngine and services initialization in the form of a
* JUnit rule.
*
*
* Usage:
*
*
*
* public class YourTest {
*
* @Rule
* public ActivitiRule activitiRule = new ActivitiRule();
*
* ...
* }
*
*
*
* The ProcessEngine and the services will be made available to the test class
* through the getters of the activitiRule. The processEngine will be
* initialized by default with the activiti.cfg.xml resource on the classpath.
* To specify a different configuration file, pass the resource location in
* {@link #ActivitiRule(String) the appropriate constructor}. Process engines
* will be cached statically. Right before the first time the setUp is called
* for a given configuration resource, the process engine will be constructed.
*
*
*
* You can declare a deployment with the {@link Deployment} annotation. This
* base class will make sure that this deployment gets deployed before the setUp
* and {@link RepositoryService#deleteDeployment(String, boolean) cascade
* deleted} after the tearDown.
*
*
*
* The activitiRule also lets you {@link ActivitiRule#setCurrentTime(Date) set
* the current time used by the process engine}. This can be handy to control the
* exact time that is used by the engine in order to verify e.g. e.g. due dates
* of timers. Or start, end and duration times in the history service. In the
* tearDown, the internal clock will automatically be reset to use the current
* system time rather then the time that was set during a test method.
*
*
* @author Tom Baeyens
*/
public class ActivitiRule implements TestRule {
protected String configurationResource = "activiti.cfg.xml";
protected String deploymentId = null;
protected ProcessEngineConfiguration processEngineConfiguration;
protected ProcessEngine processEngine;
protected RepositoryService repositoryService;
protected RuntimeService runtimeService;
protected TaskService taskService;
protected HistoryService historyService;
protected IdentityService identityService;
protected ManagementService managementService;
protected FormService formService;
protected ActivitiMockSupport mockSupport;
public ActivitiRule() {
}
public ActivitiRule(String configurationResource) {
this.configurationResource = configurationResource;
}
public ActivitiRule(ProcessEngine processEngine) {
setProcessEngine(processEngine);
}
/**
* Implementation based on {@link TestWatcher}.
*/
@Override
public Statement apply(final Statement base, final Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
List errors = new ArrayList();
startingQuietly(description, errors);
try {
base.evaluate();
succeededQuietly(description, errors);
} catch (AssumptionViolatedException e) {
errors.add(e);
skippedQuietly(e, description, errors);
} catch (Throwable t) {
errors.add(t);
failedQuietly(t, description, errors);
} finally {
finishedQuietly(description, errors);
}
MultipleFailureException.assertEmpty(errors);
}
};
}
private void succeededQuietly(Description description, List errors) {
try {
succeeded(description);
} catch (Throwable t) {
errors.add(t);
}
}
private void failedQuietly(Throwable t, Description description,
List errors) {
try {
failed(t, description);
} catch (Throwable t1) {
errors.add(t1);
}
}
private void skippedQuietly(AssumptionViolatedException e,
Description description, List errors) {
try {
skipped(e, description);
} catch (Throwable t) {
errors.add(t);
}
}
private void startingQuietly(Description description, List errors) {
try {
starting(description);
} catch (Throwable t) {
errors.add(t);
}
}
private void finishedQuietly(Description description, List errors) {
try {
finished(description);
} catch (Throwable t) {
errors.add(t);
}
}
/**
* Invoked when a test succeeds
*/
protected void succeeded(Description description) {
}
/**
* Invoked when a test fails
*/
protected void failed(Throwable e, Description description) {
}
/**
* Invoked when a test is skipped due to a failed assumption.
*/
protected void skipped(AssumptionViolatedException e, Description description) {
}
protected void starting(Description description) {
if (processEngine == null) {
initializeProcessEngine();
}
if (processEngineConfiguration == null) {
initializeServices();
}
if (mockSupport == null) {
initializeMockSupport();
}
// Allow for mock configuration
configureProcessEngine();
// Allow for annotations
try {
TestHelper.annotationMockSupportSetup(Class.forName(description.getClassName()), description.getMethodName(), mockSupport);
} catch (ClassNotFoundException e) {
throw new ActivitiException("Programmatic error: could not instantiate "
+ description.getClassName(), e);
}
try {
deploymentId = TestHelper.annotationDeploymentSetUp(processEngine,
Class.forName(description.getClassName()), description.getMethodName());
} catch (ClassNotFoundException e) {
throw new ActivitiException("Programmatic error: could not instantiate "
+ description.getClassName(), e);
}
}
protected void initializeProcessEngine() {
processEngine = TestHelper.getProcessEngine(configurationResource);
}
protected void initializeServices() {
processEngineConfiguration = processEngine.getProcessEngineConfiguration();
repositoryService = processEngine.getRepositoryService();
runtimeService = processEngine.getRuntimeService();
taskService = processEngine.getTaskService();
historyService = processEngine.getHistoryService();
identityService = processEngine.getIdentityService();
managementService = processEngine.getManagementService();
formService = processEngine.getFormService();
}
protected void initializeMockSupport() {
if (ActivitiMockSupport.isMockSupportPossible(processEngine)) {
this.mockSupport = new ActivitiMockSupport(processEngine);
}
}
protected void configureProcessEngine() {
/** meant to be overridden */
}
protected void finished(Description description) {
// Remove the test deployment
try {
TestHelper.annotationDeploymentTearDown(processEngine, deploymentId,
Class.forName(description.getClassName()), description.getMethodName());
} catch (ClassNotFoundException e) {
throw new ActivitiException("Programmatic error: could not instantiate "
+ description.getClassName(), e);
}
// Reset internal clock
processEngineConfiguration.getClock().reset();
// Rest mocks
if (mockSupport != null) {
TestHelper.annotationMockSupportTeardown(mockSupport);
}
}
public void setCurrentTime(Date currentTime) {
processEngineConfiguration.getClock().setCurrentTime(currentTime);
}
public String getConfigurationResource() {
return configurationResource;
}
public void setConfigurationResource(String configurationResource) {
this.configurationResource = configurationResource;
}
public ProcessEngine getProcessEngine() {
return processEngine;
}
public void setProcessEngine(ProcessEngine processEngine) {
this.processEngine = processEngine;
initializeServices();
}
public RepositoryService getRepositoryService() {
return repositoryService;
}
public void setRepositoryService(RepositoryService repositoryService) {
this.repositoryService = repositoryService;
}
public RuntimeService getRuntimeService() {
return runtimeService;
}
public void setRuntimeService(RuntimeService runtimeService) {
this.runtimeService = runtimeService;
}
public TaskService getTaskService() {
return taskService;
}
public void setTaskService(TaskService taskService) {
this.taskService = taskService;
}
public HistoryService getHistoryService() {
return historyService;
}
public void setHistoricDataService(HistoryService historicDataService) {
this.historyService = historicDataService;
}
public IdentityService getIdentityService() {
return identityService;
}
public void setIdentityService(IdentityService identityService) {
this.identityService = identityService;
}
public ManagementService getManagementService() {
return managementService;
}
public FormService getFormService() {
return formService;
}
public void setManagementService(ManagementService managementService) {
this.managementService = managementService;
}
public void setProcessEngineConfiguration(ProcessEngineConfigurationImpl processEngineConfiguration) {
this.processEngineConfiguration = processEngineConfiguration;
}
public ActivitiMockSupport getMockSupport() {
return mockSupport;
}
public ActivitiMockSupport mockSupport() {
return mockSupport;
}
}