2 * This document is a part of the source code and related artifacts
3 * for CollectionSpace, an open source collections management system
4 * for museums and related institutions:
6 * http://www.collectionspace.org
7 * http://wiki.collectionspace.org
9 * Copyright © 2009 Regents of the University of California
11 * Licensed under the Educational Community License (ECL), Version 2.0.
12 * You may not use this file except in compliance with this License.
14 * You may obtain a copy of the ECL 2.0 License at
15 * https://source.collectionspace.org/collection-space/LICENSE.txt
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
24 package org.collectionspace.services.client.test;
26 import java.util.ArrayList;
27 import java.util.List;
28 import javax.ws.rs.core.MultivaluedMap;
29 import javax.ws.rs.core.Response;
30 import javax.xml.bind.JAXBContext;
31 import javax.xml.bind.Marshaller;
32 import org.jboss.resteasy.client.ClientResponse;
33 import org.testng.Assert;
34 import org.testng.annotations.Test;
36 import org.collectionspace.services.collectionobject.CollectionObject;
37 import org.collectionspace.services.collectionobject.CollectionObjectList;
38 import org.collectionspace.services.client.CollectionObjectClient;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
43 * CollectionObjectServiceTest, carries out tests against a
44 * deployed and running CollectionObject Service.
46 * $LastChangedRevision$
49 public class CollectionObjectServiceTest {
51 private CollectionObjectClient collectionObjectClient = CollectionObjectClient.getInstance();
52 private String knownCollectionObjectId = null;
53 private final String NON_EXISTENT_ID = createNonExistentIdentifier();
54 final Logger logger = LoggerFactory.getLogger(CollectionObjectServiceTest.class);
57 // ---------------------------------------------------------------
58 // Service Discovery tests
59 // ---------------------------------------------------------------
64 // ---------------------------------------------------------------
65 // CRUD tests : CREATE tests
66 // ---------------------------------------------------------------
71 // NOTE The W3C HTTP spec suggests that the URL of the newly-created
72 // resource be returned in the Location header, as well as in the
73 // entity body of the response: <http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html>.
74 // If we follow this practice in our service, we might also test for the presence of
75 // these URLs in the response headers (e.g. via res.getMetadata().getFirst("Location"))
80 public void createCollectionObject() {
81 String identifier = this.createIdentifier();
83 CollectionObject collectionObject = createCollectionObject(identifier);
84 ClientResponse<Response> res = collectionObjectClient.createCollectionObject(collectionObject);
85 verbose("createCollectionObject: status = " + res.getStatus());
86 Assert.assertEquals(res.getStatus(), Response.Status.CREATED.getStatusCode());
88 // Store the ID returned from this create operation for additional tests below.
89 knownCollectionObjectId = extractId(res);
92 // Create multiple (used for Read multiple tests, below)
93 @Test(dependsOnMethods = {"createCollectionObject"})
94 public void createCollection() {
95 for(int i = 0; i < 3; i++){
96 this.createCollectionObject();
103 // Create : sending null payload
105 // Create : sending wrong schema in payload
107 // Create : sending random data in payload
109 // Invalid CollectionObject schema
110 // Question: How can we pass an empty entity body, a different (non-CollectionObject) schema,
111 // and/or 'junk' data to the service via the CollectionObjectClient?
113 // Create : with duplicate object ID
115 // Should fail with a 409 Conflict status code.
116 @Test(dependsOnMethods = {"createCollectionObject"})
117 public void createDuplicateCollectionObject() {
118 CollectionObject collectionObject = createCollectionObject(knownCollectionObjectId);
119 ClientResponse<Response> res =
120 collectionObjectClient.createCollectionObject(collectionObject);
121 verbose("createDuplicateCollectionObject: status = " + res.getStatus());
122 Assert.assertEquals(res.getStatus(), Response.Status.CONFLICT.getStatusCode());
126 // ---------------------------------------------------------------
127 // CRUD tests : READ tests
128 // ---------------------------------------------------------------
133 // These two test methods have not yet been tested:
137 @Test(dependsOnMethods = {"createCollectionObject"})
138 public void getCollectionObject() {
139 ClientResponse<CollectionObject> res =
140 collectionObjectClient.getCollectionObject(knownCollectionObjectId);
141 verbose("getCollectionObject: status = " + res.getStatus());
142 Assert.assertEquals(res.getStatus(), Response.Status.OK.getStatusCode());
150 // Read : with non-existent object ID
152 // Should fail with a 404 Not Found status code.
153 @Test(dependsOnMethods = {"createCollectionObject"})
154 public void getNonExistentCollectionObject() {
155 ClientResponse<CollectionObject> res =
156 collectionObjectClient.getCollectionObject(NON_EXISTENT_ID);
157 verbose("getNonExistentCollectionObject: status = " + res.getStatus());
158 Assert.assertEquals(res.getStatus(), Response.Status.NOT_FOUND.getStatusCode());
162 // ---------------------------------------------------------------
163 // CRUD tests : READ (list, or multiple) tests
164 // ---------------------------------------------------------------
170 @Test(dependsOnMethods = {"createCollection"})
171 public void getCollectionObjectList() {
172 // The resource method is expected to return at least an empty list
173 ClientResponse<CollectionObjectList> res = collectionObjectClient.getCollectionObjectList();
174 CollectionObjectList coList = res.getEntity();
175 verbose("getCollectionObjectList: status = " + res.getStatus());
176 Assert.assertEquals(res.getStatus(), Response.Status.OK.getStatusCode());
178 List<CollectionObjectList.CollectionObjectListItem> coItemList =
179 coList.getCollectionObjectListItem();
181 for(CollectionObjectList.CollectionObjectListItem pli : coItemList){
182 verbose("getCollectionObjectList: list-item[" + i + "] csid=" + pli.getCsid());
183 verbose("getCollectionObjectList: list-item[" + i + "] objectNumber=" + pli.getObjectNumber());
184 verbose("getCollectionObjectList: list-item[" + i + "] URI=" + pli.getUri());
194 // ---------------------------------------------------------------
195 // CRUD tests : UPDATE tests
196 // ---------------------------------------------------------------
202 @Test(dependsOnMethods = {"createCollectionObject"})
203 public void updateCollectionObject() {
204 ClientResponse<CollectionObject> res =
205 collectionObjectClient.getCollectionObject(knownCollectionObjectId);
206 verbose("getCollectionObject: status = " + res.getStatus());
207 Assert.assertEquals(res.getStatus(), Response.Status.OK.getStatusCode());
208 CollectionObject collectionObject = res.getEntity();
209 verbose("Got CollectionObject to update with ID: " + knownCollectionObjectId,
210 collectionObject, CollectionObject.class);
212 //collectionObject.setCsid("updated-" + knownCollectionObjectId);
213 collectionObject.setObjectNumber("updated-" + collectionObject.getObjectNumber());
214 collectionObject.setObjectName("updated-" + collectionObject.getObjectName());
216 // make call to update service
218 collectionObjectClient.updateCollectionObject(knownCollectionObjectId, collectionObject);
219 verbose("updateCollectionObject: status = " + res.getStatus());
220 Assert.assertEquals(res.getStatus(), Response.Status.OK.getStatusCode());
222 // check the response
223 CollectionObject updatedCollectionObject = res.getEntity();
224 Assert.assertEquals(updatedCollectionObject.getObjectName(),
225 collectionObject.getObjectName());
226 verbose("updateCollectionObject: ", updatedCollectionObject, CollectionObject.class);
232 // Update : with non-existent object ID
234 // Should fail with a 404 Not Found status code.
235 @Test(dependsOnMethods = {"updateCollectionObject"})
236 public void updateNonExistentCollectionObject() {
237 CollectionObject collectionObject = createCollectionObject(NON_EXISTENT_ID);
238 // make call to update service
239 ClientResponse<CollectionObject> res =
240 collectionObjectClient.updateCollectionObject(NON_EXISTENT_ID, collectionObject);
241 verbose("createCollectionObject: status = " + res.getStatus());
242 Assert.assertEquals(res.getStatus(), Response.Status.NOT_FOUND.getStatusCode());
246 // ---------------------------------------------------------------
247 // CRUD tests : DELETE tests
248 // ---------------------------------------------------------------
254 @Test(dependsOnMethods = {"createCollectionObject"})
255 public void deleteCollectionObject() {
256 verbose("Calling deleteCollectionObject:" + knownCollectionObjectId);
257 ClientResponse<Response> res = collectionObjectClient.deleteCollectionObject(knownCollectionObjectId);
258 verbose("deleteCollectionObject: status = " + res.getStatus());
259 Assert.assertEquals(res.getStatus(), Response.Status.OK.getStatusCode());
265 // Delete : with non-existent object ID
267 // Should fail with a 404 Not Found status code.
268 @Test(dependsOnMethods = {"deleteCollectionObject"})
269 public void deleteNonExistentCollectionObject() {
270 verbose("Calling deleteCollectionObject:" + NON_EXISTENT_ID);
271 ClientResponse<Response> res =
272 collectionObjectClient.deleteCollectionObject(NON_EXISTENT_ID);
273 verbose("deleteCollectionObject: status = " + res.getStatus());
274 Assert.assertEquals(res.getStatus(), Response.Status.NOT_FOUND.getStatusCode());
278 // ---------------------------------------------------------------
279 // Utility methods used by tests above
280 // ---------------------------------------------------------------
282 private CollectionObject createCollectionObject(String identifier) {
283 CollectionObject collectionObject = createCollectionObject("objectNumber-" + identifier,
284 "objectName-" + identifier);
286 return collectionObject;
289 private CollectionObject createCollectionObject(String objectNumber, String objectName) {
290 CollectionObject collectionObject = new CollectionObject();
292 collectionObject.setObjectNumber(objectNumber);
293 collectionObject.setObjectName(objectName);
295 return collectionObject;
298 private String extractId(ClientResponse<Response> res) {
299 MultivaluedMap mvm = res.getMetadata();
300 String uri = (String) ((ArrayList) mvm.get("Location")).get(0);
301 verbose("extractId:uri=" + uri);
302 String[] segments = uri.split("/");
303 String id = segments[segments.length - 1];
308 private void verbose(String msg) {
309 // if(logger.isInfoEnabled()){
310 // logger.debug(msg);
312 System.out.println(msg);
315 private void verbose(String msg, Object o, Class clazz) {
318 JAXBContext jc = JAXBContext.newInstance(clazz);
319 Marshaller m = jc.createMarshaller();
320 m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
322 m.marshal(o, System.out);
328 private void verboseMap(MultivaluedMap map) {
329 for(Object entry : map.entrySet()){
330 MultivaluedMap.Entry mentry = (MultivaluedMap.Entry) entry;
331 verbose(" name=" + mentry.getKey() + " value=" + mentry.getValue());
335 private String createIdentifier() {
336 long identifier = System.currentTimeMillis();
337 return Long.toString(identifier);
340 private String createNonExistentIdentifier() {
341 return Long.toString(Long.MAX_VALUE);