Hold ReST API Unit Tests

* RM-1320, RM-1328, RM-1331, RM-1333
 * added Mockito based framework for testing Java backed declarative web scripts and their templates



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@65762 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2014-03-28 01:33:48 +00:00
parent 9d66d4f6b2
commit 022c1269a4
18 changed files with 1194 additions and 27 deletions

View File

@@ -596,6 +596,9 @@
<!-- Abstract parent bean for many POST and PUT Hold beans -->
<bean id="rmBaseHold" parent="webscript" abstract="true">
<property name="holdService" ref="HoldService" />
<property name="recordService" ref="RecordService" />
<property name="recordFolderService" ref="RecordFolderService" />
<property name="nodeService" ref="NodeService" />
</bean>
<!-- REST impl for POST Hold -->

View File

@@ -25,7 +25,10 @@ import java.util.List;
import java.util.Map;
import org.alfresco.module.org_alfresco_module_rm.hold.HoldService;
import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -46,6 +49,15 @@ public abstract class BaseHold extends DeclarativeWebScript
{
/** Hold Service */
private HoldService holdService;
/** record service */
private RecordService recordService;
/** record folder service */
private RecordFolderService recordFolderService;
/** node service */
private NodeService nodeService;
/**
* Set the hold service
@@ -56,6 +68,30 @@ public abstract class BaseHold extends DeclarativeWebScript
{
this.holdService = holdService;
}
/**
* @param recordFolderService record folder service
*/
public void setRecordFolderService(RecordFolderService recordFolderService)
{
this.recordFolderService = recordFolderService;
}
/**
* @param recordService record service
*/
public void setRecordService(RecordService recordService)
{
this.recordService = recordService;
}
/**
* @param nodeService node service
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* Returns the hold service
@@ -125,17 +161,33 @@ public abstract class BaseHold extends DeclarativeWebScript
*/
protected NodeRef getItemNodeRef(JSONObject json)
{
String nodeRef = null;
String nodeRefString = null;
try
{
nodeRef = json.getString("nodeRef");
nodeRefString = json.getString("nodeRef");
}
catch (JSONException je)
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST,
"Could not get the nodeRef from the json object.", je);
}
return new NodeRef(nodeRef);
NodeRef nodeRef = new NodeRef(nodeRefString);
// ensure that the node exists
if (!nodeService.exists(nodeRef))
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Item being added to hold does not exist.");
}
// ensure that the node we are adding to the hold is a record or
// record folder
if (!recordService.isRecord(nodeRef) && !recordFolderService.isRecordFolder(nodeRef))
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Items added to a hold must be either a record or record folder.");
}
return nodeRef;
}
/**
@@ -152,8 +204,21 @@ public abstract class BaseHold extends DeclarativeWebScript
JSONArray holdsArray = json.getJSONArray("holds");
for (int i = 0; i < holdsArray.length(); i++)
{
String nodeRef = holdsArray.getString(i);
holds.add(new NodeRef(nodeRef));
NodeRef nodeRef = new NodeRef(holdsArray.getString(i));
// check the hold exists
if (!nodeService.exists(nodeRef))
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "The hold does not exist.");
}
// check the noderef is actually a hold
if (!holdService.isHold(nodeRef))
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Items are being added to a node that isn't a hold.");
}
holds.add(nodeRef);
}
}
catch (JSONException je)

View File

@@ -137,6 +137,12 @@ public class HoldsGet extends DeclarativeWebScript
if (StringUtils.isNotBlank(storeType) && StringUtils.isNotBlank(storeId) && StringUtils.isNotBlank(id))
{
filePlan = new NodeRef(new StoreRef(storeType, storeId), id);
// check that this node is actually a file plan
if (!nodeService.exists(filePlan) || !filePlanService.isFilePlan(filePlan))
{
throw new WebScriptException(Status.STATUS_NOT_FOUND, "The file plan provided could not be found.");
}
}
else
{

View File

@@ -3,7 +3,7 @@
<suite name="JUnit AllTestSuite" verbose="1" >
<test name="AllTests" junit="true">
<classes>
<class name="org.alfresco.module.org_alfresco_module_rm.AllUnitTestSuite" />
<class name="org.alfresco.module.org_alfresco_module_rm.test.AllUnitTestSuite" />
<class name="org.alfresco.module.org_alfresco_module_rm.test.AllTestSuite" />
</classes>
</test>

View File

@@ -33,8 +33,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.module.org_alfresco_module_rm.BaseUnitTest;
import org.alfresco.module.org_alfresco_module_rm.admin.RecordsManagementAdminService;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest;
import org.alfresco.repo.forms.Field;
import org.alfresco.repo.forms.FieldDefinition;
import org.alfresco.repo.forms.Form;

View File

@@ -41,7 +41,7 @@ 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.module.org_alfresco_module_rm.test.util.BaseUnitTest;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.NamespaceService;
@@ -60,6 +60,7 @@ import org.mockito.stubbing.Answer;
* Hold service implementation unit test
*
* @author Roy Wetherall
* @since 2.2
*/
public class HoldServiceImplUnitTest extends BaseUnitTest
{

View File

@@ -29,8 +29,8 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.alfresco.module.org_alfresco_module_rm.BaseUnitTest;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.RegexQNamePattern;
@@ -42,6 +42,7 @@ import org.mockito.Spy;
* Transfer evaluator unit test.
*
* @author Roy Wetherall
* @since 2.2
*/
public class TransferEvaluatorUnitTest extends BaseUnitTest
{

View File

@@ -23,7 +23,7 @@ import static org.mockito.Mockito.verify;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.module.org_alfresco_module_rm.BaseUnitTest;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest;
import org.alfresco.service.namespace.QName;
import org.junit.Test;
import org.mockito.InjectMocks;
@@ -32,6 +32,7 @@ import org.mockito.InjectMocks;
* Unit test for RecordMetadataBootstrap
*
* @author Roy Wetherall
* @since 2.2
*/
public class RecordMetadataBootstrapUnitTest extends BaseUnitTest
{

View File

@@ -26,7 +26,7 @@ import static org.mockito.Mockito.when;
import java.util.Map;
import java.util.Set;
import org.alfresco.module.org_alfresco_module_rm.BaseUnitTest;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.apache.commons.collections.CollectionUtils;
@@ -38,6 +38,7 @@ import org.mockito.InjectMocks;
* Unit test for RecordServiceImpl
*
* @author Roy Wetherall
* @since 2.2
*/
public class RecordServiceImplUnitTest extends BaseUnitTest
{

View File

@@ -0,0 +1,39 @@
package org.alfresco.module.org_alfresco_module_rm.script.hold;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseWebScriptUnitTest;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* Base hold web script unit test.
*
* @author Roy Wetherall
* @since 2.2
*/
public abstract class BaseHoldWebScriptUnitTest extends BaseWebScriptUnitTest
{
/** test holds */
protected NodeRef hold1NodeRef;
protected NodeRef hold2NodeRef;
protected List<NodeRef> holds;
/**
* @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest#before()
*/
@Override
public void before()
{
super.before();
// generate test holds
hold1NodeRef = generateHoldNodeRef("hold1");
hold2NodeRef = generateHoldNodeRef("hold2");
// list of holds
holds = new ArrayList<NodeRef>(2);
Collections.addAll(holds, hold1NodeRef, hold2NodeRef);
}
}

View File

@@ -0,0 +1,205 @@
package org.alfresco.module.org_alfresco_module_rm.script.hold;
import static org.alfresco.module.org_alfresco_module_rm.test.util.WebScriptExceptionMatcher.badRequest;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;
import java.util.Collections;
import java.util.List;
import org.alfresco.service.cmr.repository.NodeRef;
import org.junit.Test;
import org.springframework.extensions.webscripts.WebScriptException;
/**
* Base hold web script with content unit test.
*
* @author Roy Wetherall
* @since 2.2
*/
public abstract class BaseHoldWebScriptWithContentUnitTest extends BaseHoldWebScriptUnitTest
{
/**
* Helper method to build JSON content to send to hold webscripts.
*/
protected String buildContent(NodeRef nodeRef, List<NodeRef> holds)
{
StringBuilder builder = new StringBuilder(255);
builder.append("{");
if (nodeRef != null)
{
builder.append("'nodeRef':'").append(nodeRef.toString()).append("'");
}
if (nodeRef != null && holds != null)
{
builder.append(",");
}
if (holds != null)
{
builder.append("'holds':[");
boolean bFirst = true;
for (NodeRef hold : holds)
{
if (bFirst == false)
{
builder.append(",");
}
else
{
bFirst = false;
}
builder.append("'" + hold.toString() + "'");
}
builder.append("]");
}
builder.append("}");
return builder.toString();
}
/**
* Test for expected exception when invalid JSON sent
*/
@SuppressWarnings("unchecked")
@Test
public void sendInvalidJSON() throws Exception
{
// invalid JSON
String content = "invalid JSON";
// expected exception
exception.expect(WebScriptException.class);
exception.expect(badRequest());
// execute web script
executeWebScript(Collections.EMPTY_MAP, content);
}
/**
* Test for expected exception when one of the holds doesn't exist.
*/
@SuppressWarnings("unchecked")
@Test
public void holdDoesNotExist() throws Exception
{
// setup interactions
when(mockedNodeService.exists(eq(hold1NodeRef))).thenReturn(false);
// build content
String content = buildContent(record, holds);
// expected exception
exception.expect(WebScriptException.class);
exception.expect(badRequest());
// execute web script
executeWebScript(Collections.EMPTY_MAP, content);
}
/**
* Test for expected excpetion when the item being added to the hold
* does not exist.
*/
@SuppressWarnings("unchecked")
@Test
public void nodeRefDoesNotExist() throws Exception
{
// setup interactions
when(mockedNodeService.exists(eq(record))).thenReturn(false);
// build content
String content = buildContent(record, holds);
// expected exception
exception.expect(WebScriptException.class);
exception.expect(badRequest());
// execute web script
executeWebScript(Collections.EMPTY_MAP, content);
}
/**
* Test for expected exception when hold information is missing from
* sent JSON.
*/
@SuppressWarnings("unchecked")
@Test
public void holdMissingFromContent() throws Exception
{
// build content
String content = buildContent(record, null);
// expected exception
exception.expect(WebScriptException.class);
exception.expect(badRequest());
// execute web script
executeWebScript(Collections.EMPTY_MAP, content);
}
/**
* Test for expected exception when noderef information is missing
* from send JSON.
*/
@SuppressWarnings("unchecked")
@Test
public void nodeRefMissingFromContent() throws Exception
{
// build content
String content = buildContent(null, holds);
// expected exception
exception.expect(WebScriptException.class);
exception.expect(badRequest());
// execute web script
executeWebScript(Collections.EMPTY_MAP, content);
}
/**
* Test for expected exception when adding an item to something
* that isn't a hold.
*/
@SuppressWarnings("unchecked")
@Test
public void holdIsNotAHold() throws Exception
{
// build json content to send to server
List<NodeRef> notAHold = Collections.singletonList(recordFolder);
String content = buildContent(record, notAHold);
// expected exception
exception.expect(WebScriptException.class);
exception.expect(badRequest());
// execute web script
executeWebScript(Collections.EMPTY_MAP, content);
}
/**
* Test for expected exception when adding an item to a hold
* that isn't a record or record folder.
*/
@SuppressWarnings("unchecked")
@Test
public void nodeRefIsNotARecordOrRecordFolder() throws Exception
{
// build json content to send to server
List<NodeRef> notAHold = Collections.singletonList(recordFolder);
String content = buildContent(filePlanComponent, notAHold);
// expected exception
exception.expect(WebScriptException.class);
exception.expect(badRequest());
// execute web script
executeWebScript(Collections.EMPTY_MAP, content);
}
}

View File

@@ -0,0 +1,100 @@
/*
* 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.script.hold;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import java.util.Collections;
import org.json.JSONObject;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Spy;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
/**
* Hold ReST API POST implementation unit test.
*
* @author Roy Wetherall
* @since 2.2
*/
public class HoldPostUnitTest extends BaseHoldWebScriptWithContentUnitTest
{
/** classpath location of ftl template for web script */
private static final String WEBSCRIPT_TEMPLATE = WEBSCRIPT_ROOT_RM + "hold.post.json.ftl";
/** HoldPost webscript instance */
protected @Spy @InjectMocks HoldPost webScript;
/**
* @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseWebScriptUnitTest#getWebScript()
*/
@Override
protected DeclarativeWebScript getWebScript()
{
return webScript;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseWebScriptUnitTest#getWebScriptTemplate()
*/
@Override
protected String getWebScriptTemplate()
{
return WEBSCRIPT_TEMPLATE;
}
/**
* Test that a record can be added to holds.
*/
@SuppressWarnings("unchecked")
@Test
public void addRecordToHolds() throws Exception
{
// build json to send to server
String content = buildContent(record, holds);
// execute web script
JSONObject json = executeJSONWebScript(Collections.EMPTY_MAP, content);
assertNotNull(json);
// verify that the record was added to the holds
verify(mockedHoldService, times(1)).addToHolds(holds, record);
}
/**
* Test that a record folder can be added to holds.
*/
@SuppressWarnings("unchecked")
@Test
public void addRecordFolderToHolds() throws Exception
{
// build json to send to server
String content = buildContent(recordFolder, holds);
// execute web script
JSONObject json = executeJSONWebScript(Collections.EMPTY_MAP, content);
assertNotNull(json);
// verify that the record was added to the holds
verify(mockedHoldService, times(1)).addToHolds(holds, recordFolder);
}
}

View File

@@ -0,0 +1,100 @@
/*
* 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.script.hold;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import java.util.Collections;
import org.json.JSONObject;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Spy;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
/**
* Hold ReST API PUT implementation unit test.
*
* @author Roy Wetherall
* @since 2.2
*/
public class HoldPutUnitTest extends BaseHoldWebScriptWithContentUnitTest
{
/** classpath location of ftl template for web script */
private static final String WEBSCRIPT_TEMPLATE = WEBSCRIPT_ROOT_RM + "hold.put.json.ftl";
/** HoldPut webscript instance */
protected @Spy @InjectMocks HoldPut webScript;
/**
* @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseWebScriptUnitTest#getWebScript()
*/
@Override
protected DeclarativeWebScript getWebScript()
{
return webScript;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseWebScriptUnitTest#getWebScriptTemplate()
*/
@Override
protected String getWebScriptTemplate()
{
return WEBSCRIPT_TEMPLATE;
}
/**
* Test that a record can be removed from holds.
*/
@SuppressWarnings("unchecked")
@Test
public void removeRecordFromHolds() throws Exception
{
// build json to send to server
String content = buildContent(record, holds);
// execute web script
JSONObject json = executeJSONWebScript(Collections.EMPTY_MAP, content);
assertNotNull(json);
// verify that the record was removed from holds
verify(mockedHoldService, times(1)).removeFromHolds(holds, record);
}
/**
* Test that a record folder can be removed from holds.
*/
@SuppressWarnings("unchecked")
@Test
public void removeRecordFolderFromHolds() throws Exception
{
// build json to send to server
String content = buildContent(recordFolder, holds);
// execute web script
JSONObject json = executeJSONWebScript(Collections.EMPTY_MAP, content);
assertNotNull(json);
// verify that the record was removed from holds
verify(mockedHoldService, times(1)).removeFromHolds(holds, recordFolder);
}
}

View File

@@ -0,0 +1,233 @@
/*
* 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.script.hold;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doReturn;
import static org.alfresco.module.org_alfresco_module_rm.test.util.WebScriptExceptionMatcher.fileNotFound;
import java.util.Collections;
import java.util.Map;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
import org.json.JSONArray;
import org.json.JSONObject;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Spy;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.WebScriptException;
/**
* Holds ReST API GET implementation unit test.
*
* @author Roy Wetherall
* @since 2.2
*/
public class HoldsGetUnitTest extends BaseHoldWebScriptUnitTest
{
/** classpath location of ftl template for web script */
private static final String WEBSCRIPT_TEMPLATE = WEBSCRIPT_ROOT_RM + "holds.get.json.ftl";
/** HoldsGet webscript instance */
protected @Spy @InjectMocks HoldsGet webScript;
/**
* @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseWebScriptUnitTest#getWebScript()
*/
@Override
protected DeclarativeWebScript getWebScript()
{
return webScript;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseWebScriptUnitTest#getWebScriptTemplate()
*/
@Override
protected String getWebScriptTemplate()
{
return WEBSCRIPT_TEMPLATE;
}
/**
* Test the outcome of calling the web script with an invalid file plan
*/
@Test
public void invalidFilePlan() throws Exception
{
// setup web script parameters
Map<String, String> parameters = buildParameters
(
"store_type", filePlan.getStoreRef().getProtocol(),
"store_id", filePlan.getStoreRef().getIdentifier(),
"id", "imadethisup"
);
// setup expected exception
exception.expect(WebScriptException.class);
exception.expect(fileNotFound());
// execute web script
executeWebScript(parameters);
}
/**
* Test the outcome of calling the web script with no file plan specified
* and with no default file plan created.
*/
@SuppressWarnings("unchecked")
@Test
public void defaultFilePlanDoesNotExist() throws Exception
{
// setup expected exception
exception.expect(WebScriptException.class);
exception.expect(fileNotFound());
// execute web script
executeWebScript(Collections.EMPTY_MAP);
}
/**
* Test the successful retrieval of holds defined for a specified file
* plan.
*/
@Test
public void getHoldsForFilePlan() throws Exception
{
// setup interactions
doReturn(holds).when(mockedHoldService).getHolds(filePlan);
// setup web script parameters
Map<String, String> parameters = buildParameters
(
"store_type", filePlan.getStoreRef().getProtocol(),
"store_id", filePlan.getStoreRef().getIdentifier(),
"id", filePlan.getId()
);
// execute web script
JSONObject json = executeJSONWebScript(parameters);
assertNotNull(json);
// check the JSON result
testForBothHolds(json);
}
/**
* Test the retrieval of holds for the default file plan.
*/
@SuppressWarnings("unchecked")
@Test
public void getHoldsForDefaultFilePlan() throws Exception
{
// setup interactions
doReturn(holds).when(mockedHoldService).getHolds(filePlan);
doReturn(filePlan).when(mockedFilePlanService).getFilePlanBySiteId(FilePlanService.DEFAULT_RM_SITE_ID);
// execute web script
JSONObject json = executeJSONWebScript(Collections.EMPTY_MAP);
assertNotNull(json);
// check the JSON result
testForBothHolds(json);
}
/**
* Test the retrieval of holds that hold a specified node.
*/
@Test
public void getHoldsThatNodeRefIsHeldBy() throws Exception
{
// setup interactions
doReturn(holds).when(mockedHoldService).heldBy(record, true);
// setup web script parameters
Map<String, String> parameters = buildParameters
(
"store_type", filePlan.getStoreRef().getProtocol(),
"store_id", filePlan.getStoreRef().getIdentifier(),
"id", filePlan.getId(),
"itemNodeRef", record.toString()
);
// execute web script
JSONObject json = executeJSONWebScript(parameters);
assertNotNull(json);
// check the JSON result
testForBothHolds(json);
}
/**
* Test the retrieval of holds that a node is not held in.
*/
@Test
public void getHoldsThatNodeRefIsNotHeldBy() throws Exception
{
// setup interactions
doReturn(holds).when(mockedHoldService).heldBy(record, false);
// setup web script parameters
Map<String, String> parameters = buildParameters
(
"store_type", filePlan.getStoreRef().getProtocol(),
"store_id", filePlan.getStoreRef().getIdentifier(),
"id", filePlan.getId(),
"itemNodeRef", record.toString(),
"includedInHold", "false"
);
// execute web script
JSONObject json = executeJSONWebScript(parameters);
assertNotNull(json);
// check the JSON result
testForBothHolds(json);
}
/**
* Helper method to test JSON object for the presence of both test holds.
*
* @param json json result from web script
*/
private void testForBothHolds(JSONObject json) throws Exception
{
// check the JSON result
assertTrue(json.has("data"));
assertTrue(json.getJSONObject("data").has("holds"));
JSONArray jsonHolds = json.getJSONObject("data").getJSONArray("holds");
assertNotNull(jsonHolds);
assertEquals(2, jsonHolds.length());
JSONObject hold1 = jsonHolds.getJSONObject(0);
assertNotNull(hold1);
assertEquals("hold1", hold1.getString("name"));
assertEquals(hold1NodeRef.toString(), hold1.getString("nodeRef"));
JSONObject hold2 = jsonHolds.getJSONObject(1);
assertNotNull(hold2);
assertEquals("hold2", hold2.getString("name"));
assertEquals(hold2NodeRef.toString(), hold2.getString("nodeRef"));
}
}

View File

@@ -16,13 +16,16 @@
* 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;
package org.alfresco.module.org_alfresco_module_rm.test;
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.jscript.app.evaluator.TransferEvaluatorUnitTest;
import org.alfresco.module.org_alfresco_module_rm.record.RecordMetadataBootstrapUnitTest;
import org.alfresco.module.org_alfresco_module_rm.record.RecordServiceImplUnitTest;
import org.alfresco.module.org_alfresco_module_rm.script.hold.HoldPostUnitTest;
import org.alfresco.module.org_alfresco_module_rm.script.hold.HoldPutUnitTest;
import org.alfresco.module.org_alfresco_module_rm.script.hold.HoldsGetUnitTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@@ -40,7 +43,10 @@ import org.junit.runners.Suite.SuiteClasses;
RecordServiceImplUnitTest.class,
RecordsManagementTypeFormFilterUnitTest.class,
HoldServiceImplUnitTest.class,
TransferEvaluatorUnitTest.class
TransferEvaluatorUnitTest.class,
HoldsGetUnitTest.class,
HoldPostUnitTest.class,
HoldPutUnitTest.class
})
public class AllUnitTestSuite
{

View File

@@ -16,7 +16,7 @@
* 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;
package org.alfresco.module.org_alfresco_module_rm.test.util;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
@@ -29,6 +29,7 @@ import java.util.List;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
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.record.RecordService;
@@ -44,13 +45,19 @@ import org.alfresco.service.namespace.QNamePattern;
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;
/**
* Unit test for RecordServiceImpl
* 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
{
@@ -69,6 +76,11 @@ public class BaseUnitTest implements RecordsManagementModel
@Mock(name="filePlanService") protected FilePlanService mockedFilePlanService;
@Mock(name="recordFolderService") protected RecordFolderService mockedRecordFolderService;
@Mock(name="recordService") protected RecordService mockedRecordService;
@Mock(name="holdService") protected HoldService mockedHoldService;
/** expected exception rule */
@Rule
public ExpectedException exception = ExpectedException.none();
/**
* Test method setup
@@ -78,19 +90,21 @@ public class BaseUnitTest implements RecordsManagementModel
{
MockitoAnnotations.initMocks(this);
// setup file plan
filePlan = generateNodeRef(TYPE_FILE_PLAN);
doReturn(true).when(mockedFilePlanService).isFilePlan(filePlan);
// setup basic file plan component
filePlanComponent = generateNodeRef();
setupAsFilePlanComponent(filePlanComponent);
// set-up namespace service
when(mockedNamespaceService.getNamespaceURI(RM_PREFIX)).thenReturn(RM_URI);
when(mockedNamespaceService.getPrefixes(RM_URI)).thenReturn(CollectionUtils.unmodifiableSet(RM_PREFIX));
// 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();
doReturn(true).when(mockedRecordFolderService).isRecordFolder(recordFolder);
record = generateRecord();
doReturn(true).when(mockedRecordService).isRecord(record);
// set record as child of record folder
List<ChildAssociationRef> result = new ArrayList<ChildAssociationRef>(1);
@@ -112,41 +126,84 @@ public class BaseUnitTest implements RecordsManagementModel
return QName.createQName(RM_URI, GUID.generate());
}
/**
* 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);
return recordFolder;
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(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)
{
NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, GUID.generate());
when(mockedNodeService.exists(nodeRef)).thenReturn(true);
when(mockedNodeService.exists(eq(nodeRef))).thenReturn(true);
if (type != null)
{
when(mockedNodeService.getType(nodeRef)).thenReturn(type);
when(mockedNodeService.getType(eq(nodeRef))).thenReturn(type);
}
return nodeRef;
}

View File

@@ -0,0 +1,269 @@
/*
* 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.test.util;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import org.json.JSONObject;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.extensions.surf.util.Content;
import org.springframework.extensions.webscripts.Container;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.Description;
import org.springframework.extensions.webscripts.Description.RequiredCache;
import org.springframework.extensions.webscripts.DescriptionExtension;
import org.springframework.extensions.webscripts.FormatRegistry;
import org.springframework.extensions.webscripts.Match;
import org.springframework.extensions.webscripts.ScriptProcessorRegistry;
import org.springframework.extensions.webscripts.SearchPath;
import org.springframework.extensions.webscripts.TemplateProcessorRegistry;
import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.extensions.webscripts.WebScriptResponse;
import org.springframework.extensions.webscripts.json.JSONUtils;
import org.springframework.extensions.webscripts.processor.FTLTemplateProcessor;
import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.TemplateLoader;
/**
* Base Web Script Unit Test.
* <p>
* Provides helper methods that mock the nessesery classes needed to execute
* a Java backed webscript that implements DeclarativeWebScript.
* <p>
* Note that execution of java script controllers is not currently supported.
*
* @author Roy Wetherall
* @since 2.2
*/
public abstract class BaseWebScriptUnitTest extends BaseUnitTest
{
/** web script root folder for RM webscripts */
protected static final String WEBSCRIPT_ROOT_RM = "alfresco/templates/webscripts/org/alfresco/rma/";
/**
* @return declarative webscript
*/
protected abstract DeclarativeWebScript getWebScript();
/**
* @return classpath location of webscript template
*/
protected abstract String getWebScriptTemplate();
/**
* Helper method to build a map of web script parameter values
* mimicking those provided on the URL
*
* @param values
* @return
*/
protected Map<String, String> buildParameters(String ... values)
{
Map<String, String> result = new HashMap<String, String>(values.length/2);
for (int i = 0; i < values.length; i=i+2)
{
String key = values[i];
String value = values[i+1];
result.put(key, value);
}
return result;
}
/**
*
* @param parameters
* @return
* @throws Exception
*/
protected JSONObject executeJSONWebScript(Map<String, String> parameters) throws Exception
{
return executeJSONWebScript(parameters, null);
}
/**
* Execute web script and convert result into a JSON object.
*
* @param parameters map of all parameter values
* @return {@link JSONObject} result, parsed into a JSON object
*/
protected JSONObject executeJSONWebScript(Map<String, String> parameters, String content) throws Exception
{
String result = executeWebScript(parameters, content);
return new JSONObject(result);
}
/**
*
* @param parameters
* @return
* @throws Exception
*/
protected String executeWebScript(Map<String, String> parameters) throws Exception
{
return executeWebScript( parameters, null);
}
/**
* Execute web script and return result as a string.
*
* @param parameters map of all parameter values
* @return {@link String} result of web script
*/
protected String executeWebScript(Map<String, String> parameters, String content) throws Exception
{
DeclarativeWebScript webScript = getWebScript();
String template = getWebScriptTemplate();
// initialise webscript
webScript.init(getMockedContainer(template), getMockedDescription());
// execute webscript
WebScriptResponse mockedResponse = getMockedWebScriptResponse();
webScript.execute(getMockedWebScriptRequest(webScript, parameters, content), mockedResponse);
// return results
return mockedResponse.getWriter().toString();
}
/**
* Helper method to get the mocked web script request.
*
* @param webScript declarative web script
* @param parameters web script parameter values
* @return {@link WebScriptRequest} mocked web script request
*/
@SuppressWarnings("rawtypes")
protected WebScriptRequest getMockedWebScriptRequest(DeclarativeWebScript webScript, final Map<String, String> parameters, String content) throws Exception
{
Match match = new Match(null, parameters, null, webScript);
org.springframework.extensions.webscripts.Runtime mockedRuntime = mock(org.springframework.extensions.webscripts.Runtime.class);
WebScriptRequest mockedRequest = mock(WebScriptRequest.class);
doReturn(match).when(mockedRequest).getServiceMatch();
doReturn(mockedRuntime).when(mockedRequest).getRuntime();
if (content != null && !content.isEmpty())
{
Content mockedContent = mock(Content.class);
doReturn(content).when(mockedContent).getContent();
doReturn(mockedContent).when(mockedRequest).getContent();
}
String [] paramNames = (String[])parameters.keySet().toArray(new String[parameters.size()]);
doReturn(paramNames).when(mockedRequest).getParameterNames();
doAnswer(new Answer()
{
@Override
public Object answer(InvocationOnMock invocation) throws Throwable
{
String paramName = (String)invocation.getArguments()[0];
return parameters.get(paramName);
}
}).when(mockedRequest).getParameter(anyString());
doReturn(new String[0]).when(mockedRequest).getHeaderNames();
doReturn("json").when(mockedRequest).getFormat();
return mockedRequest;
}
/**
* Helper method to get mocked web script response
*
* @return {@link WebScriptResponse} mocked web script response
*/
protected WebScriptResponse getMockedWebScriptResponse() throws Exception
{
WebScriptResponse mockedResponse = mock(WebScriptResponse.class);
StringWriter writer = new StringWriter();
doReturn(writer).when(mockedResponse).getWriter();
return mockedResponse;
}
/**
* Helper method to get mocked container object.
*
* @param template classpath location of webscripts ftl template
* @return {@link Container} mocked container
*/
protected Container getMockedContainer(String template) throws Exception
{
FormatRegistry mockedFormatRegistry = mock(FormatRegistry.class);
doReturn("application/json").when(mockedFormatRegistry).getMimeType(anyString(), anyString());
ScriptProcessorRegistry mockedScriptProcessorRegistry = mock(ScriptProcessorRegistry.class);
doReturn(null).when(mockedScriptProcessorRegistry).findValidScriptPath(anyString());
TemplateProcessorRegistry mockedTemplateProcessorRegistry = mock(TemplateProcessorRegistry.class);
doReturn(template).when(mockedTemplateProcessorRegistry).findValidTemplatePath(anyString());
FTLTemplateProcessor ftlTemplateProcessor = new FTLTemplateProcessor()
{
@Override
protected TemplateLoader getTemplateLoader()
{
return new ClassTemplateLoader(getClass(), "/");
}
};
ftlTemplateProcessor.init();
doReturn(ftlTemplateProcessor).when(mockedTemplateProcessorRegistry).getTemplateProcessor(anyString());
Container mockedContainer = mock(Container.class);
doReturn(mockedFormatRegistry).when(mockedContainer).getFormatRegistry();
doReturn(mockedScriptProcessorRegistry).when(mockedContainer).getScriptProcessorRegistry();
doReturn(mockedTemplateProcessorRegistry).when(mockedContainer).getTemplateProcessorRegistry();
Map<String, Object> containerTemplateParameters = new HashMap<String, Object>(5);
containerTemplateParameters.put("jsonUtils", new JSONUtils());
doReturn(containerTemplateParameters).when(mockedContainer).getTemplateParameters();
SearchPath mockedSearchPath = mock(SearchPath.class);
doReturn(false).when(mockedSearchPath).hasDocument(anyString());
doReturn(mockedSearchPath).when(mockedContainer).getSearchPath();
// setup description
Description mockDescription = mock(Description.class);
doReturn(mock(RequiredCache.class)).when(mockDescription).getRequiredCache();
return mockedContainer;
}
/**
* Helper method to get mocked description class
*
* @return {@link DescriptionExtension} mocked description class
*/
protected Description getMockedDescription()
{
Description mockedDescription = mock(Description.class);
doReturn(mock(RequiredCache.class)).when(mockedDescription).getRequiredCache();
return mockedDescription;
}
}

View File

@@ -0,0 +1,80 @@
package org.alfresco.module.org_alfresco_module_rm.test.util;
import org.junit.internal.matchers.TypeSafeMatcher;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException;
/**
* Web script exception matcher.
* <p>
* Allows use to check whether the raised web script exception has the correct
* status number or not.
*
* @author Roy Wetherall
* @since 2.2
*/
@SuppressWarnings("deprecation")
public class WebScriptExceptionMatcher extends TypeSafeMatcher<WebScriptException>
{
/**
* Helper method to create a matcher for the file not found (404)
* exception status.
*
* @return {@link WebScriptExceptionMatcher}
*/
public static WebScriptExceptionMatcher fileNotFound()
{
return new WebScriptExceptionMatcher(Status.STATUS_NOT_FOUND);
}
/**
* Helper method to create a matcher for the bad request status (400)
* exception status.
*
* @return {@link WebScriptExceptionMatcher}
*/
public static WebScriptExceptionMatcher badRequest()
{
return new WebScriptExceptionMatcher(Status.STATUS_BAD_REQUEST);
}
/** expected status */
public int expectedStatus;
/** actual status */
public int actualStatus;
/**
* Constructor
*
* @param expectedStatus expected status
*/
public WebScriptExceptionMatcher(int expectedStatus)
{
this.expectedStatus = expectedStatus;
}
/**
* Determines if the expected outcome matches the actual
* outcome.
*
* @return true if matches, false otherwise
*/
@Override
public boolean matchesSafely(WebScriptException exception)
{
actualStatus = exception.getStatus();
return (actualStatus == expectedStatus);
}
/**
* Describe unexpected outcome.
*/
@Override
public void describeTo(org.hamcrest.Description description)
{
description.appendValue(actualStatus)
.appendText(" was found instead of ")
.appendValue(expectedStatus);
}
}