package org.imixs.workflow.engine; import static org.mockito.Mockito.when; import java.io.IOException; import java.io.InputStream; import java.security.Principal; import java.text.ParseException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Logger; import javax.ejb.SessionContext; import javax.xml.parsers.ParserConfigurationException; import org.imixs.workflow.ItemCollection; import org.imixs.workflow.Model; import org.imixs.workflow.ModelManager; import org.imixs.workflow.WorkflowContext; import org.imixs.workflow.WorkflowKernel; import org.imixs.workflow.bpmn.BPMNModel; import org.imixs.workflow.bpmn.BPMNParser; import org.imixs.workflow.exceptions.AccessDeniedException; import org.imixs.workflow.exceptions.ModelException; import org.imixs.workflow.exceptions.PluginException; import org.imixs.workflow.exceptions.ProcessingErrorException; import org.junit.Before; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.Spy; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.xml.sax.SAXException; /** * Abstract base class for jUnit tests using the WorkflowService. * * This test class mocks a complete workflow environment without the class * WorkflowService * * The test class generates a test database with process entities and activity * entities which can be accessed from a plug-in or the workflowKernel. * * A JUnit Test can save, load and process workitems. * * JUnit tests can also manipulate the model by changing entities through * calling the methods: * * getActivityEntity,setActivityEntity,getProcessEntity,setProcessEntity * * * @version 2.0 * @see AbstractPluginTest, TestWorkflowService * @author rsoika */ public class AbstractWorkflowEnvironment { private final static Logger logger = Logger.getLogger(AbstractWorkflowEnvironment.class.getName()); public static final String DEFAULT_MODEL_VERSION = "1.0.0"; Map<String, ItemCollection> database = null; protected DocumentService documentService; protected WorkflowService workflowService; @Spy protected ModelService modelService; protected SessionContext ctx; protected WorkflowContext workflowContext; private BPMNModel model = null; private String modelPath = "/bpmn/plugin-test.bpmn"; public String getModelPath() { return modelPath; } public void setModelPath(String modelPath) { this.modelPath = modelPath; } @Before public void setup() throws PluginException, AccessDeniedException, ProcessingErrorException, ModelException { MockitoAnnotations.initMocks(this); // setup db createTestDatabase(); // mock session context ctx = Mockito.mock(SessionContext.class); // simulate SessionContext ctx.getCallerPrincipal().getName() Principal principal = Mockito.mock(Principal.class); when(principal.getName()).thenReturn("manfred"); when(ctx.getCallerPrincipal()).thenReturn(principal); // mock Entity service documentService = Mockito.mock(DocumentService.class); // Simulate fineProfile("1.0.0") -> entityService.load()... when(documentService.load(Mockito.anyString())).thenAnswer(new Answer<ItemCollection>() { @Override public ItemCollection answer(InvocationOnMock invocation) throws Throwable { Object[] args = invocation.getArguments(); String id = (String) args[0]; ItemCollection result = database.get(id); if (result != null) { // set author access=true result.replaceItemValue(WorkflowService.ISAUTHOR, true); } return result; } }); // simulate save() method when(documentService.save(Mockito.any(ItemCollection.class))).thenAnswer(new Answer<ItemCollection>() { @Override public ItemCollection answer(InvocationOnMock invocation) throws Throwable { Object[] args = invocation.getArguments(); ItemCollection entity = (ItemCollection) args[0]; database.put(entity.getItemValueString(WorkflowKernel.UNIQUEID), entity); return entity; } }); // Mock modelService (using the @spy) annotation Mockito.doNothing().when(modelService).init(); // load default model loadModel(); // Mock modelManager ModelManager modelManager = Mockito.mock(ModelManager.class); try { when(modelManager.getModel(Mockito.anyString())).thenReturn(this.getModel()); when(modelManager.getModelByWorkitem(Mockito.any(ItemCollection.class))).thenReturn(this.getModel()); } catch (ModelException e) { e.printStackTrace(); } // Mock context workflowContext = Mockito.mock(WorkflowContext.class); when(workflowContext.getModelManager()).thenReturn(modelManager); // Mock WorkflowService workflowService = Mockito.mock(WorkflowService.class); workflowService.documentService = documentService; workflowService.ctx = ctx; workflowService.modelService = modelService; when(workflowService.getModelManager()).thenReturn(modelService); when(workflowService.getWorkListByRef(Mockito.anyString())).thenAnswer(new Answer<List<ItemCollection>>() { @Override public List<ItemCollection> answer(InvocationOnMock invocation) throws Throwable { List<ItemCollection> result = new ArrayList<>(); Object[] args = invocation.getArguments(); String id = (String) args[0]; // iterate over all data and return matching workitems. Collection<ItemCollection> allEntities = database.values(); for (ItemCollection aentity : allEntities) { if (aentity.getItemValueString(WorkflowService.UNIQUEIDREF).equals(id)) { result.add(aentity); } } return result; } }); when(workflowService.processWorkItem(Mockito.any(ItemCollection.class))).thenCallRealMethod(); when(workflowService.getUserName()).thenCallRealMethod(); when(workflowService.getWorkItem(Mockito.anyString())).thenCallRealMethod(); try { when(workflowService.getEvents(Mockito.any(ItemCollection.class))).thenCallRealMethod(); } catch (ModelException e) { e.printStackTrace(); } } /** * Create a test database with some workItems and a simple model */ protected void createTestDatabase() { database = new HashMap<String, ItemCollection>(); ItemCollection entity = null; logger.info("createSimpleDatabase...."); // create workitems for (int i = 1; i < 6; i++) { entity = new ItemCollection(); entity.replaceItemValue("type", "workitem"); entity.replaceItemValue(WorkflowKernel.UNIQUEID, "W0000-0000" + i); entity.replaceItemValue("txtName", "Workitem " + i); entity.replaceItemValue("$ModelVersion", "1.0.0"); entity.replaceItemValue("$ProcessID", 100); entity.replaceItemValue("$ActivityID", 10); entity.replaceItemValue(WorkflowService.ISAUTHOR, true); database.put(entity.getItemValueString(WorkflowKernel.UNIQUEID), entity); } } public Model getModel() { return model; } public void loadModel() { InputStream inputStream = getClass().getResourceAsStream(this.modelPath); try { model = BPMNParser.parseModel(inputStream, "UTF-8"); this.modelService.addModel(model); } catch (ModelException | ParseException | ParserConfigurationException | SAXException | IOException e) { e.printStackTrace(); } } public Map<String, ItemCollection> getDatabase() { return database; } }