Hold Service Improvements:

* HoldService API explanded beyound immediate use case needs to form a more complete API, plus some tweaks to method names
 * unit test (via Mockito) added .. still some todo's (see RM-1326)
 * integration test added .. to test behaviour interactions (see RM-1326)
 * method level permissions added to Hold service .. should see filtering of results based on permissions
 * added behaviour to HoldService to unfreeze records and record folders when hold is deleted (same as old relinquish action)
 * deprecation of dupliacte methods found in FreezeService
 * fix up use of deprecated methods throughout code .. note that warnings have only been hidden in actions that are soon to be deprecated too



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@64834 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2014-03-19 05:02:04 +00:00
parent e6f1c48f53
commit e0cdb0d2d0
30 changed files with 1495 additions and 894 deletions

View File

@@ -19,6 +19,7 @@
package org.alfresco.module.org_alfresco_module_rm;
import org.alfresco.module.org_alfresco_module_rm.forms.RecordsManagementTypeFormFilterUnitTest;
import org.alfresco.module.org_alfresco_module_rm.hold.HoldServiceImplUnitTest;
import org.alfresco.module.org_alfresco_module_rm.record.RecordMetadataBootstrapUnitTest;
import org.alfresco.module.org_alfresco_module_rm.record.RecordServiceImplUnitTest;
import org.junit.runner.RunWith;
@@ -36,7 +37,8 @@ import org.junit.runners.Suite.SuiteClasses;
{
RecordMetadataBootstrapUnitTest.class,
RecordServiceImplUnitTest.class,
RecordsManagementTypeFormFilterUnitTest.class
RecordsManagementTypeFormFilterUnitTest.class,
HoldServiceImplUnitTest.class
})
public class AllUnitTestSuite
{

View File

@@ -20,6 +20,7 @@ package org.alfresco.module.org_alfresco_module_rm;
import static org.mockito.Mockito.when;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
import org.alfresco.module.org_alfresco_module_rm.identifier.IdentifierService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.service.cmr.dictionary.DictionaryService;
@@ -41,22 +42,28 @@ import org.mockito.MockitoAnnotations;
*/
public class BaseUnitTest implements RecordsManagementModel
{
protected static NodeRef FILE_PLAN_COMPONENT = generateNodeRef();
protected static NodeRef FILE_PLAN = generateNodeRef();
protected NodeRef filePlanComponent;
protected NodeRef filePlan;
/** 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;
/** rm service mocks */
@Mock(name="filePlanService") protected FilePlanService mockedFilePlanService;
@Before
public void before()
{
MockitoAnnotations.initMocks(this);
filePlanComponent = generateNodeRef();
filePlan = generateNodeRef(TYPE_FILE_PLAN);
// set-up node service
when(mockedNodeService.getProperty(FILE_PLAN_COMPONENT, PROP_ROOT_NODEREF)).thenReturn(FILE_PLAN);
when(mockedNodeService.getType(FILE_PLAN)).thenReturn(TYPE_FILE_PLAN);
when(mockedNodeService.getProperty(filePlanComponent, PROP_ROOT_NODEREF)).thenReturn(filePlan);
// set-up namespace service
when(mockedNamespaceService.getNamespaceURI(RM_PREFIX)).thenReturn(RM_URI);
@@ -69,8 +76,19 @@ public class BaseUnitTest implements RecordsManagementModel
return QName.createQName(RM_URI, GUID.generate());
}
protected static NodeRef generateNodeRef()
protected NodeRef generateNodeRef()
{
return new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, GUID.generate());
return generateNodeRef(null);
}
protected NodeRef generateNodeRef(QName type)
{
NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, GUID.generate());
when(mockedNodeService.exists(nodeRef)).thenReturn(true);
if (type != null)
{
when(mockedNodeService.getType(nodeRef)).thenReturn(type);
}
return nodeRef;
}
}

View File

@@ -0,0 +1,312 @@
/*
* Copyright (C) 2005-2014 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* 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/>.
*/
package org.alfresco.module.org_alfresco_module_rm.hold;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.doAnswer;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.BaseUnitTest;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Spy;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
/**
* Hold service implementation unit test
*
* @author Roy Wetherall
*/
public class HoldServiceImplUnitTest extends BaseUnitTest
{
/** test values */
private static final String HOLD_NAME = "holdname";
private static final String HOLD_REASON = "holdreason";
private static final String HOLD_DESCRIPTION = "holddescription";
protected NodeRef holdContainer;
protected NodeRef hold;
protected NodeRef hold2;
protected NodeRef notHold;
@Spy @InjectMocks HoldServiceImpl holdService;
@Before
@Override
public void before()
{
super.before();
holdContainer = generateNodeRef(TYPE_HOLD_CONTAINER);
hold = generateNodeRef(TYPE_HOLD);
hold2 = generateNodeRef(TYPE_HOLD);
notHold = generateNodeRef(TYPE_RECORD_CATEGORY);
when(mockedFilePlanService.getHoldContainer(filePlan)).thenReturn(holdContainer);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Test
public void beforeDeleteNode()
{
doAnswer(new Answer<Void>()
{
@Override
public Void answer(InvocationOnMock invocation) throws Exception
{
Object[] args = invocation.getArguments();
((RunAsWork)args[0]).doWork();
return null;
}
}).when(holdService).runAsSystem(any(RunAsWork.class));
}
@Test
public void isHold()
{
assertTrue(holdService.isHold(hold));
assertFalse(holdService.isHold(notHold));
}
@Test
public void getHolds()
{
// with no holds
List<NodeRef> emptyHoldList = holdService.getHolds(filePlan);
verify(mockedNodeService).getChildAssocs(holdContainer, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
assertNotNull(emptyHoldList);
assertTrue(emptyHoldList.isEmpty());
// set up list of two holds
List<ChildAssociationRef> list = new ArrayList<ChildAssociationRef>(2);
list.add(new ChildAssociationRef(generateQName(), holdContainer, generateQName(), hold));
list.add(new ChildAssociationRef(generateQName(), holdContainer, generateQName(), hold2));
when(mockedNodeService.getChildAssocs(holdContainer, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL)).thenReturn(list);
// with 2 holds
List<NodeRef> holdsList = holdService.getHolds(filePlan);
verify(mockedNodeService, times(2)).getChildAssocs(holdContainer, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
assertNotNull(holdsList);
assertEquals(2, holdsList.size());
// check one of the holds
NodeRef holdFromList = holdsList.get(0);
assertEquals(TYPE_HOLD, mockedNodeService.getType(holdFromList));
}
@Test
public void heldBy()
{
// TODO
}
@Test (expected=AlfrescoRuntimeException.class)
public void getHold()
{
// setup node service interactions
when(mockedNodeService.getChildByName(eq(holdContainer), eq(ContentModel.ASSOC_CONTAINS), anyString())).thenReturn(null)
.thenReturn(hold)
.thenReturn(notHold);
// no hold
NodeRef noHold = holdService.getHold(filePlan, "notAHold");
assertNull(noHold);
// found hold
NodeRef someHold = holdService.getHold(filePlan, "someHold");
assertNotNull(someHold);
assertEquals(TYPE_HOLD, mockedNodeService.getType(someHold));
// ensure runtime exception is thrown
holdService.getHold(filePlan, "notHold");
}
@Test
public void getHeld()
{
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Test
public void createHold()
{
// setup node service interactions
when(mockedNodeService.createNode(eq(holdContainer), eq(ContentModel.ASSOC_CONTAINS), any(QName.class) , eq(TYPE_HOLD), any(Map.class)))
.thenReturn(new ChildAssociationRef(ContentModel.ASSOC_CONTAINS, holdContainer, generateQName(), hold));
// create hold
NodeRef newHold = holdService.createHold(filePlan, HOLD_NAME, HOLD_REASON, HOLD_DESCRIPTION);
assertNotNull(newHold);
assertEquals(TYPE_HOLD, mockedNodeService.getType(newHold));
assertEquals(hold, newHold);
// check the node service interactions
ArgumentCaptor<Map> propertyMapCaptor = ArgumentCaptor.forClass(Map.class);
ArgumentCaptor<QName> assocNameCaptor = ArgumentCaptor.forClass(QName.class);
verify(mockedNodeService).createNode(eq(holdContainer), eq(ContentModel.ASSOC_CONTAINS), assocNameCaptor.capture() , eq(TYPE_HOLD), propertyMapCaptor.capture());
// check property map
Map<QName, Serializable> propertyMap = (Map<QName, Serializable>)propertyMapCaptor.getValue();
assertNotNull(propertyMap);
assertEquals(3, propertyMap.size());
assertTrue(propertyMap.containsKey(ContentModel.PROP_NAME));
assertEquals(HOLD_NAME, propertyMap.get(ContentModel.PROP_NAME));
assertTrue(propertyMap.containsKey(ContentModel.PROP_DESCRIPTION));
assertEquals(HOLD_DESCRIPTION, propertyMap.get(ContentModel.PROP_DESCRIPTION));
assertTrue(propertyMap.containsKey(PROP_HOLD_REASON));
assertEquals(HOLD_REASON, propertyMap.get(PROP_HOLD_REASON));
// check assoc name
assertNotNull(assocNameCaptor.getValue());
assertEquals(NamespaceService.CONTENT_MODEL_1_0_URI, assocNameCaptor.getValue().getNamespaceURI());
assertEquals(HOLD_NAME, assocNameCaptor.getValue().getLocalName());
}
@Test
public void getHoldReason()
{
// setup node service interactions
when(mockedNodeService.exists(hold))
.thenReturn(false)
.thenReturn(true)
.thenReturn(true)
.thenReturn(true);
when(mockedNodeService.getProperty(eq(hold), eq(PROP_HOLD_REASON)))
.thenReturn(null)
.thenReturn(HOLD_REASON);
// node does not exist
assertNull(holdService.getHoldReason(hold));
// node isn't a hold
assertNull(holdService.getHoldReason(notHold));
// hold reason isn't set
assertNull(holdService.getHoldReason(hold));
// hold reason set
assertEquals(HOLD_REASON, holdService.getHoldReason(hold));
}
@Test
public void setHoldReason()
{
// setup node service interactions
when(mockedNodeService.exists(hold))
.thenReturn(false)
.thenReturn(true)
.thenReturn(true);
// node does not exist
holdService.setHoldReason(hold, HOLD_REASON);
verify(mockedNodeService, never()).setProperty(hold, PROP_HOLD_REASON, HOLD_REASON);
// node isn't a hold
holdService.setHoldReason(notHold, HOLD_REASON);
verify(mockedNodeService, never()).setProperty(hold, PROP_HOLD_REASON, HOLD_REASON);
// set hold reason
holdService.setHoldReason(hold, HOLD_REASON);
verify(mockedNodeService).setProperty(hold, PROP_HOLD_REASON, HOLD_REASON);
}
@Test
public void deleteHold()
{
// setup node service interactions
when(mockedNodeService.exists(hold))
.thenReturn(false)
.thenReturn(true)
.thenReturn(true);
// node does not exist
holdService.deleteHold(hold);
verify(mockedNodeService, never()).deleteNode(hold);
// node isn't a hold
holdService.deleteHold(notHold);
verify(mockedNodeService, never()).deleteNode(hold);
// delete hold
holdService.deleteHold(hold);
verify(mockedNodeService).deleteNode(hold);
// TODO check interactions with policy component!!!
}
@Test
public void addToHold()
{
// TODO
}
@Test
public void addToHolds()
{
// TODO
}
@Test
public void removeFromHold()
{
// TODO
}
@Test
public void removeFromHolds()
{
// TODO
}
@Test
public void removeFromAllHolds()
{
}
}

View File

@@ -41,8 +41,8 @@ import org.mockito.InjectMocks;
*/
public class RecordServiceImplUnitTest extends BaseUnitTest
{
private static NodeRef NON_STANDARD_FILE_PLAN_COMPONENT = generateNodeRef();
private static NodeRef NON_STANDARD_FILE_PLAN = generateNodeRef();
private NodeRef nonStandardFilePlanComponent;
private NodeRef nonStandardFilePlan;
private static QName TYPE_MY_FILE_PLAN = generateQName();
private static QName ASPECT_FOR_FILE_PLAN = generateQName();
@@ -58,9 +58,11 @@ public class RecordServiceImplUnitTest extends BaseUnitTest
{
super.before();
nonStandardFilePlanComponent = generateNodeRef();
nonStandardFilePlan = generateNodeRef(TYPE_MY_FILE_PLAN);
// set-up node service
when(mockedNodeService.getProperty(NON_STANDARD_FILE_PLAN_COMPONENT, PROP_ROOT_NODEREF)).thenReturn(NON_STANDARD_FILE_PLAN);
when(mockedNodeService.getType(NON_STANDARD_FILE_PLAN)).thenReturn(TYPE_MY_FILE_PLAN);
when(mockedNodeService.getProperty(nonStandardFilePlanComponent, PROP_ROOT_NODEREF)).thenReturn(nonStandardFilePlan);
// set-up dictionary service
when(mockedDictionaryService.getAllAspects()).thenReturn(CollectionUtils.EMPTY_COLLECTION);
@@ -90,13 +92,13 @@ public class RecordServiceImplUnitTest extends BaseUnitTest
recordService.registerRecordMetadataAspect(ASPECT_FOR_BOTH, TYPE_FILE_PLAN);
recordService.registerRecordMetadataAspect(ASPECT_FOR_BOTH, TYPE_MY_FILE_PLAN);
Set<QName> set = recordService.getRecordMetadataAspects(FILE_PLAN_COMPONENT);
Set<QName> set = recordService.getRecordMetadataAspects(filePlanComponent);
assertNotNull(set);
assertEquals(2, set.size());
assertTrue(set.contains(ASPECT_FOR_FILE_PLAN));
assertTrue(set.contains(ASPECT_FOR_BOTH));
set = recordService.getRecordMetadataAspects(NON_STANDARD_FILE_PLAN_COMPONENT);
set = recordService.getRecordMetadataAspects(nonStandardFilePlanComponent);
assertNotNull(set);
assertEquals(2, set.size());
assertTrue(set.contains(ASPECT_FOR_MY_FILE_PLAN));