/* * #%L * Alfresco Records Management Module * %% * Copyright (C) 2005 - 2016 Alfresco Software Limited * %% * This file is part of the Alfresco software. * - * If the software was purchased under a paid Alfresco license, the terms of * the paid license agreement will prevail. Otherwise, the software is * provided under the following open source license terms: * - * Alfresco is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * Alfresco is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * #L% */ package org.alfresco.module.org_alfresco_module_rm.test.util; import static org.alfresco.module.org_alfresco_module_rm.test.util.AlfMock.generateQName; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.alfresco.model.ContentModel; import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementActionService; import org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditService; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService; import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; import org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService; import org.alfresco.module.org_alfresco_module_rm.hold.HoldService; import org.alfresco.module.org_alfresco_module_rm.identifier.IdentifierService; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.model.rma.type.CmObjectType; import org.alfresco.module.org_alfresco_module_rm.model.security.ModelSecurityService; import org.alfresco.module.org_alfresco_module_rm.record.RecordService; import org.alfresco.module.org_alfresco_module_rm.recordableversion.RecordableVersionConfigService; import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService; import org.alfresco.module.org_alfresco_module_rm.report.ReportService; import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService; import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService; import org.alfresco.module.org_alfresco_module_rm.util.AlfrescoTransactionSupport; import org.alfresco.module.org_alfresco_module_rm.util.AuthenticationUtil; import org.alfresco.module.org_alfresco_module_rm.util.TransactionalResourceHelper; import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionService; import org.alfresco.repo.policy.BehaviourFilter; import org.alfresco.repo.policy.PolicyComponent; import org.alfresco.repo.security.permissions.impl.ExtendedPermissionService; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.CopyService; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.security.AuthorityService; import org.alfresco.service.cmr.security.OwnableService; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QNamePattern; import org.alfresco.service.namespace.RegexQNamePattern; import org.alfresco.util.GUID; import org.alfresco.util.collections.CollectionUtils; import org.junit.Before; import org.junit.Rule; import org.junit.rules.ExpectedException; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.springframework.context.ApplicationContext; /** * Base unit test. * <p> * Contains core and records management service mocks ready for injection. Helper methods * provide an easy way to build RM or Alfresco constructs for use in tests. * * @author Roy Wetherall * @since 2.2 */ public class BaseUnitTest implements RecordsManagementModel, ContentModel { protected NodeRef filePlanComponent; protected NodeRef filePlan; protected NodeRef recordFolder; protected NodeRef record; /** core service mocks */ @Mock(name="nodeService") protected NodeService mockedNodeService; @Mock(name="dictionaryService") protected DictionaryService mockedDictionaryService; @Mock(name="namespaceService") protected NamespaceService mockedNamespaceService; @Mock(name="identifierService") protected IdentifierService mockedIdentifierService; @Mock(name="permissionService") protected PermissionService mockedPermissionService; @Mock(name="ownableService") protected OwnableService mockedOwnableService; @Mock(name="searchService") protected SearchService mockedSearchService; @Mock(name="retryingTransactionHelper") protected RetryingTransactionHelper mockedRetryingTransactionHelper; @Mock(name="authorityService") protected AuthorityService mockedAuthorityService; @Mock(name="policyComponent") protected PolicyComponent mockedPolicyComponent; @Mock(name="copyService") protected CopyService mockedCopyService; @Mock(name="fileFolderService") protected FileFolderService mockedFileFolderService; @Mock(name="modelSecurityService") protected ModelSecurityService mockedModelSecurityService; /** rm service mocks */ @Mock(name="filePlanService") protected FilePlanService mockedFilePlanService; @Mock(name="recordFolderService") protected RecordFolderService mockedRecordFolderService; @Mock(name="recordService") protected RecordService mockedRecordService; @Mock(name="holdService") protected HoldService mockedHoldService; @Mock(name="recordsManagementActionService") protected RecordsManagementActionService mockedRecordsManagementActionService; @Mock(name="reportService") protected ReportService mockedReportService; @Mock(name="filePlanRoleService") protected FilePlanRoleService mockedFilePlanRoleService; @Mock(name="recordsManagementAuditService") protected RecordsManagementAuditService mockedRecordsManagementAuditService; @Mock(name="policyBehaviourFilter") protected BehaviourFilter mockedBehaviourFilter; @Mock(name="authenticationUtil") protected AuthenticationUtil mockedAuthenticationUtil; @Mock(name="extendedPermissionService") protected ExtendedPermissionService mockedExtendedPermissionService; @Mock(name="extendedSecurityService") protected ExtendedSecurityService mockedExtendedSecurityService; @Mock(name="recordableVersionConfigService") protected RecordableVersionConfigService mockedRecordableVersionConfigService; @Mock(name="cmObjectType") protected CmObjectType mockedCmObjectType; @Mock(name="recordableVersionService") protected RecordableVersionService mockedRecordableVersionService; @Mock(name="transactionalResourceHelper") protected TransactionalResourceHelper mockedTransactionalResourceHelper; @Mock(name="alfrescoTransactionSupport") protected AlfrescoTransactionSupport mockedAlfrescoTransactionSupport; @Mock(name="freezeService") protected FreezeService mockedFreezeService; @Mock(name="dispositionService") protected DispositionService mockedDispositionService; /** application context mock */ @Mock(name="applicationContext") protected ApplicationContext mockedApplicationContext; /** expected exception rule */ @Rule public ExpectedException exception = ExpectedException.none(); /** * Test method setup */ @SuppressWarnings("unchecked") @Before public void before() throws Exception { MockitoAnnotations.initMocks(this); // setup application context doReturn(mockedNodeService).when(mockedApplicationContext).getBean("dbNodeService"); // setup retrying transaction helper Answer<Object> doInTransactionAnswer = new Answer<Object>() { @SuppressWarnings("rawtypes") @Override public Object answer(InvocationOnMock invocation) throws Throwable { RetryingTransactionCallback callback = (RetryingTransactionCallback)invocation.getArguments()[0]; return callback.execute(); } }; doAnswer(doInTransactionAnswer).when(mockedRetryingTransactionHelper).<Object>doInTransaction(any(RetryingTransactionCallback.class)); // setup mocked authentication util MockAuthenticationUtilHelper.setup(mockedAuthenticationUtil); // setup file plan filePlan = generateNodeRef(TYPE_FILE_PLAN); setupAsFilePlanComponent(filePlan); doReturn(true).when(mockedFilePlanService).isFilePlan(filePlan); // setup basic file plan component filePlanComponent = generateNodeRef(); setupAsFilePlanComponent(filePlanComponent); // setup namespace service doReturn(RM_URI).when(mockedNamespaceService).getNamespaceURI(RM_PREFIX); doReturn(CollectionUtils.unmodifiableSet(RM_PREFIX)).when(mockedNamespaceService).getPrefixes(RM_URI); // setup record folder and record recordFolder = generateRecordFolder(); record = generateRecord(); // set record as child of record folder List<ChildAssociationRef> result = new ArrayList<ChildAssociationRef>(1); result.add(new ChildAssociationRef(ContentModel.ASSOC_CONTAINS, recordFolder, generateQName(RM_URI), record, true, 1)); doReturn(result).when(mockedNodeService).getChildAssocs(eq(recordFolder), eq(ContentModel.ASSOC_CONTAINS), any(QNamePattern.class)); doReturn(result).when(mockedNodeService).getParentAssocs(record); doReturn(Collections.singletonList(recordFolder)).when(mockedRecordFolderService).getRecordFolders(record); doReturn(Collections.singletonList(record)).when(mockedRecordService).getRecords(recordFolder); } /** * Helper method to generate hold reference * * @param name hold name * @return {@link NodeRef} node reference that will behave like a hold */ protected NodeRef generateHoldNodeRef(String name) { NodeRef hold = generateNodeRef(TYPE_HOLD); doReturn(name).when(mockedNodeService).getProperty(hold, ContentModel.PROP_NAME); doReturn(true).when(mockedHoldService).isHold(hold); return hold; } /** * Helper method to generate record folder reference * * @return {@link NodeRef} node reference that will behave like a record folder */ protected NodeRef generateRecordFolder() { NodeRef recordFolder = generateNodeRef(TYPE_RECORD_FOLDER); setupAsFilePlanComponent(recordFolder); doReturn(true).when(mockedRecordFolderService).isRecordFolder(recordFolder); return recordFolder; } /** * Helper method to generate a record node reference. * * @return {@link NodeRef} node reference that will behave like a record or type cm:content */ protected NodeRef generateRecord() { NodeRef record = generateNodeRef(ContentModel.TYPE_CONTENT); setupAsFilePlanComponent(record); doReturn(true).when(mockedNodeService).hasAspect(record, ASPECT_RECORD); doReturn(true).when(mockedRecordService).isRecord(record); return record; } /** * Helper method to setup a node reference as a file plan component. * * @param nodeRef {@link NodeRef} node reference that will now behave like a file plan component */ protected void setupAsFilePlanComponent(NodeRef nodeRef) { doReturn(true).when(mockedNodeService).hasAspect(nodeRef, ASPECT_FILE_PLAN_COMPONENT); doReturn(true).when(mockedFilePlanService).isFilePlanComponent(nodeRef); doReturn(filePlan).when(mockedFilePlanService).getFilePlan(nodeRef); doReturn(filePlan).when(mockedNodeService).getProperty(nodeRef, PROP_ROOT_NODEREF); } /** * Helper method to generate a node reference. * * @return {@link NodeRef} node reference that behaves like a node that exists in the spaces store */ protected NodeRef generateNodeRef() { return generateNodeRef(null); } /** * Helper method to generate a node reference of a particular type. * * @param type content type qualified name * @return {@link NodeRef} node reference that behaves like a node that exists in the spaces store with * the content type provided */ protected NodeRef generateNodeRef(QName type) { return generateNodeRef(type, true); } /** * Helper method to generate a cm:content node reference with a given name. * * @param name content name * @return NodeRef node reference */ protected NodeRef generateCmContent(String name) { NodeRef nodeRef = generateNodeRef(ContentModel.TYPE_CONTENT, true); doReturn(name).when(mockedNodeService).getProperty(nodeRef, ContentModel.PROP_NAME); return nodeRef; } /** * Helper method to generate a node reference of a particular type with a given existence characteristic. * * @param type content type qualified name * @param exists indicates whether this node should behave like a node that exists or not * @return {@link NodeRef} node reference that behaves like a node that exists (or not) in the spaces store with * the content type provided */ protected NodeRef generateNodeRef(QName type, boolean exists) { NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, GUID.generate()); when(mockedNodeService.exists(eq(nodeRef))).thenReturn(exists); if (type != null) { when(mockedNodeService.getType(eq(nodeRef))).thenReturn(type); } return nodeRef; } /** * Helper method to generate a mocked child association reference. * * @param parent parent node (optional) * @param child child node (optional) * @return {@link ChildAssociationRef} mocked to return the parent and child nodes */ protected ChildAssociationRef generateChildAssociationRef(NodeRef parent, NodeRef child) { ChildAssociationRef mockedChildAssociationRef = mock(ChildAssociationRef.class); if (parent != null) { doReturn(parent).when(mockedChildAssociationRef).getParentRef(); } if (child != null) { doReturn(child).when(mockedChildAssociationRef).getChildRef(); } return mockedChildAssociationRef; } /** * Helper method to make one node the primary parent of the other. * <p> * Assumes the cm:contains assoc type. * * @param child * @param parent */ protected void makePrimaryParentOf(NodeRef child, NodeRef parent) { makePrimaryParentOf(child, parent, ContentModel.ASSOC_CONTAINS, generateQName()); } protected void makePrimaryParentOf(NodeRef child, NodeRef parent, QName assocType, QName assocName) { makePrimaryParentOf(child, parent, assocType, assocName, mockedNodeService); } protected void makePrimaryParentOf(NodeRef child, NodeRef parent, QName assocType, QName assocName, NodeService mockedNodeService) { doReturn(new ChildAssociationRef(assocType, parent, assocName, child)) .when(mockedNodeService) .getPrimaryParent(child); } /** * Helper method to make a number of nodes children of another. * <p> * Assumes the cm:contains assoc type. * * @param parent * @param children */ protected void makeChildrenOf(NodeRef parent, NodeRef ... children) { List<ChildAssociationRef> assocs = new ArrayList<ChildAssociationRef>(children.length); for (NodeRef child : children) { assocs.add(new ChildAssociationRef(ContentModel.ASSOC_CONTAINS, parent, generateQName(), child)); doReturn(assocs).when(mockedNodeService).getParentAssocs(child); } doReturn(assocs).when(mockedNodeService).getChildAssocs(parent, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL); } @SuppressWarnings("unchecked") protected <T> List<T> buildList(T ... values) { List<T> result = new ArrayList<T>(values.length); for (T value : values) { result.add(value); } return result; } }