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.
23 package org.collectionspace.services.client.test;
25 import java.util.ArrayList;
26 import java.util.List;
27 import javax.ws.rs.core.MediaType;
28 import javax.ws.rs.core.Response;
30 import org.collectionspace.services.client.CollectionObjectClient;
31 import org.collectionspace.services.collectionobject.CollectionobjectsCommon;
32 import org.collectionspace.services.collectionobject.domain.naturalhistory.CollectionobjectsNaturalhistory;
33 import org.collectionspace.services.collectionobject.CollectionobjectsCommonList;
34 import org.collectionspace.services.collectionobject.ResponsibleDepartmentList;
35 import org.jboss.resteasy.client.ClientResponse;
37 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
38 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
39 import org.jboss.resteasy.plugins.providers.multipart.OutputPart;
40 import org.testng.Assert;
41 import org.testng.annotations.AfterClass;
42 import org.testng.annotations.Test;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
48 * CollectionObjectServiceTest, carries out tests against a
49 * deployed and running CollectionObject Service.
51 * $LastChangedRevision$
54 public class CollectionObjectServiceTest extends AbstractServiceTestImpl {
56 private final Logger logger =
57 LoggerFactory.getLogger(CollectionObjectServiceTest.class);
58 // Instance variables specific to this test.
59 private CollectionObjectClient client = new CollectionObjectClient();
60 private String knownResourceId = null;
61 private List<String> allResourceIdsCreated = new ArrayList();
62 private boolean multivalue; //toggle
65 * This method is called only by the parent class, AbstractServiceTest
68 protected String getServicePathComponent() {
69 return client.getServicePathComponent();
72 // ---------------------------------------------------------------
73 // CRUD tests : CREATE tests
74 // ---------------------------------------------------------------
77 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
78 public void create(String testName) throws Exception {
80 // Perform setup, such as initializing the type of service request
81 // (e.g. CREATE, DELETE), its valid and expected status codes, and
82 // its associated HTTP method name (e.g. POST, DELETE).
83 setupCreate(testName);
85 // Submit the request to the service and store the response.
86 String identifier = createIdentifier();
87 MultipartOutput multipart =
88 createCollectionObjectInstance(client.getCommonPartName(), identifier);
89 ClientResponse<Response> res = client.create(multipart);
90 int statusCode = res.getStatus();
92 // Check the status code of the response: does it match
93 // the expected response(s)?
96 // Does it fall within the set of valid status codes?
97 // Does it exactly match the expected status code?
98 if (logger.isDebugEnabled()) {
99 logger.debug(testName + ": status = " + statusCode);
101 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
102 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
103 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
105 // Store the ID returned from the first resource created
106 // for additional tests below.
107 if (knownResourceId == null) {
108 knownResourceId = extractId(res);
109 if (logger.isDebugEnabled()) {
110 logger.debug(testName + ": knownResourceId=" + knownResourceId);
114 // Store the IDs from every resource created by tests,
115 // so they can be deleted after tests have been run.
116 allResourceIdsCreated.add(extractId(res));
121 * Tests to diagnose and verify the fixed status of CSPACE-1026,
122 * "Whitespace at certain points in payload cause failure"
124 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
125 dependsOnMethods = {"create", "testSubmitRequest"})
126 public void createFromXmlCambridge(String testName) throws Exception {
128 createFromXmlFile(testName, "./test-data/testCambridge.xml", true);
129 testSubmitRequest(newId);
132 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
133 dependsOnMethods = {"create", "testSubmitRequest"})
134 public void createFromXmlRFWS1(String testName) throws Exception {
136 createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp1.xml", false);
137 testSubmitRequest(newId);
140 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
141 dependsOnMethods = {"create", "testSubmitRequest"})
142 public void createFromXmlRFWS2(String testName) throws Exception {
144 createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp2.xml", false);
145 testSubmitRequest(newId);
148 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
149 dependsOnMethods = {"create", "testSubmitRequest"})
150 public void createFromXmlRFWS3(String testName) throws Exception {
152 createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp3.xml", false);
153 testSubmitRequest(newId);
156 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
157 dependsOnMethods = {"create", "testSubmitRequest"})
158 public void createFromXmlRFWS4(String testName) throws Exception {
160 createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp4.xml", false);
161 testSubmitRequest(newId);
165 * Tests to diagnose and verify the fixed status of CSPACE-1248,
166 * "Wedged records created!" (i.e. records with child repeatable
167 * fields, which contain null values, can be successfully created
168 * but an error occurs on trying to retrieve those records).
170 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
171 dependsOnMethods = {"create", "testSubmitRequest"})
172 public void createWithNullValueRepeatableField(String testName) throws Exception {
174 createFromXmlFile(testName, "./target/test-classes/test-data/repfield_null1.xml", false);
175 if (logger.isDebugEnabled()) {
176 logger.debug("Successfully created record with null value repeatable field.");
177 logger.debug("Attempting to retrieve just-created record ...");
179 testSubmitRequest(newId);
183 * @see org.collectionspace.services.client.test.ServiceTest#createList()
186 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
187 dependsOnMethods = {"create"})
188 public void createList(String testName) throws Exception {
189 for (int i = 0; i < 3; i++) {
195 // Placeholders until the three tests below can be uncommented.
196 // See Issue CSPACE-401.
198 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
199 public void createWithEmptyEntityBody(String testName) throws Exception {
203 * Test how the service handles XML that is not well formed,
204 * when sent in the payload of a Create request.
206 * @param testName The name of this test method. This name is supplied
207 * automatically, via reflection, by a TestNG 'data provider' in
211 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
212 public void createWithMalformedXml(String testName) throws Exception {
213 setupCreate(testName);
217 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
218 public void createWithWrongXmlSchema(String testName) throws Exception {
224 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
225 dependsOnMethods = {"create", "testSubmitRequest"})
226 public void createWithEmptyEntityBody(String testName) throwsException {
229 setupCreateWithEmptyEntityBody(testName);
231 // Submit the request to the service and store the response.
232 String method = REQUEST_TYPE.httpMethodName();
233 String url = getServiceRootURL();
234 String mediaType = MediaType.APPLICATION_XML;
235 final String entity = "";
236 int statusCode = submitRequest(method, url, mediaType, entity);
238 // Check the status code of the response: does it match
239 // the expected response(s)?
240 if(logger.isDebugEnabled()){
241 logger.debug(testName + ": url=" + url +
242 " status=" + statusCode);
244 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
245 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
246 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
250 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
251 dependsOnMethods = {"create", "testSubmitRequest"})
252 public void createWithMalformedXml(String testName) throws Exception {
255 setupCreateWithMalformedXml(testName);
257 // Submit the request to the service and store the response.
258 String method = REQUEST_TYPE.httpMethodName();
259 String url = getServiceRootURL();
260 String mediaType = MediaType.APPLICATION_XML;
261 final String entity = MALFORMED_XML_DATA; // Constant from base class.
262 int statusCode = submitRequest(method, url, mediaType, entity);
264 // Check the status code of the response: does it match
265 // the expected response(s)?
266 if(logger.isDebugEnabled()){
267 logger.debug(testName + ": url=" + url +
268 " status=" + statusCode);
270 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
271 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
272 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
276 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
277 dependsOnMethods = {"create", "testSubmitRequest"})
278 public void createWithWrongXmlSchema(String testName) throws Exception {
281 setupCreateWithWrongXmlSchema(testName);
283 // Submit the request to the service and store the response.
284 String method = REQUEST_TYPE.httpMethodName();
285 String url = getServiceRootURL();
286 String mediaType = MediaType.APPLICATION_XML;
287 final String entity = WRONG_XML_SCHEMA_DATA;
288 int statusCode = submitRequest(method, url, mediaType, entity);
290 // Check the status code of the response: does it match
291 // the expected response(s)?
292 if(logger.isDebugEnabled()){
293 logger.debug(testName + ": url=" + url +
294 " status=" + statusCode);
296 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
297 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
298 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
303 * Test how the service handles, in a Create request, payloads
304 * containing null values (or, in the case of String fields,
305 * empty String values) in one or more fields which must be
306 * present and are required to contain non-empty values.
308 * This is a test of code and/or configuration in the service's
309 * validation routine(s).
311 * @param testName The name of this test method. This name is supplied
312 * automatically, via reflection, by a TestNG 'data provider' in
315 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
316 public void createWithRequiredValuesNullOrEmpty(String testName) throws Exception {
317 setupCreate(testName);
319 // Build a payload with invalid content, by omitting a
320 // field (objectNumber) which must be present, and in which
321 // a non-empty value is required, as enforced by the service's
322 // validation routine(s).
323 CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
324 collectionObject.setTitle("atitle");
325 collectionObject.setObjectName("some name");
327 // Submit the request to the service and store the response.
328 MultipartOutput multipart =
329 createCollectionObjectInstance(client.getCommonPartName(), collectionObject, null);
330 ClientResponse<Response> res = client.create(multipart);
331 int statusCode = res.getStatus();
333 // Read the response and verify that the create attempt failed.
334 if (logger.isDebugEnabled()) {
335 logger.debug(testName + ": status = " + statusCode);
337 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
338 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
339 Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
341 // FIXME: Consider splitting off the following into its own test method.
343 // Build a payload with invalid content, by setting a value to the
344 // empty String, in a field that requires a non-empty value,
345 // as enforced by the service's validation routine(s).
346 collectionObject = new CollectionobjectsCommon();
347 collectionObject.setTitle("atitle");
348 collectionObject.setObjectName("some name");
349 collectionObject.setObjectNumber("");
351 // Submit the request to the service and store the response.
353 createCollectionObjectInstance(client.getCommonPartName(), collectionObject, null);
354 res = client.create(multipart);
355 statusCode = res.getStatus();
357 // Read the response and verify that the create attempt failed.
358 if (logger.isDebugEnabled()) {
359 logger.debug(testName + ": status = " + statusCode);
361 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
362 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
363 Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
368 // ---------------------------------------------------------------
369 // CRUD tests : READ tests
370 // ---------------------------------------------------------------
373 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
374 dependsOnMethods = {"create"})
375 public void read(String testName) throws Exception {
380 // Submit the request to the service and store the response.
381 ClientResponse<MultipartInput> res = client.read(knownResourceId);
382 int statusCode = res.getStatus();
384 // Check the status code of the response: does it match
385 // the expected response(s)?
386 if (logger.isDebugEnabled()) {
387 logger.debug(testName + ": status = " + statusCode);
389 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
390 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
391 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
393 MultipartInput input = (MultipartInput) res.getEntity();
395 if (logger.isDebugEnabled()) {
396 logger.debug(testName + ": Reading Common part ...");
398 CollectionobjectsCommon collectionObject =
399 (CollectionobjectsCommon) extractPart(input,
400 client.getCommonPartName(), CollectionobjectsCommon.class);
401 Assert.assertNotNull(collectionObject);
403 if (logger.isDebugEnabled()) {
404 logger.debug(testName + ": Reading Natural History part ...");
406 CollectionobjectsNaturalhistory conh =
407 (CollectionobjectsNaturalhistory) extractPart(input,
408 getNHPartName(), CollectionobjectsNaturalhistory.class);
409 Assert.assertNotNull(conh);
414 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
415 dependsOnMethods = {"read"})
416 public void readNonExistent(String testName) throws Exception {
419 setupReadNonExistent(testName);
421 // Submit the request to the service and store the response.
422 ClientResponse<MultipartInput> res = client.read(NON_EXISTENT_ID);
423 int statusCode = res.getStatus();
425 // Check the status code of the response: does it match
426 // the expected response(s)?
427 if (logger.isDebugEnabled()) {
428 logger.debug(testName + ": status = " + statusCode);
430 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
431 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
432 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
435 // ---------------------------------------------------------------
436 // CRUD tests : READ_LIST tests
437 // ---------------------------------------------------------------
440 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
441 dependsOnMethods = {"createList", "read"})
442 public void readList(String testName) throws Exception {
445 setupReadList(testName);
447 // Submit the request to the service and store the response.
448 ClientResponse<CollectionobjectsCommonList> res = client.readList();
449 CollectionobjectsCommonList list = res.getEntity();
450 int statusCode = res.getStatus();
452 // Check the status code of the response: does it match
453 // the expected response(s)?
454 if (logger.isDebugEnabled()) {
455 logger.debug(testName + ": status = " + statusCode);
457 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
458 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
459 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
461 // Optionally output additional data about list members for debugging.
462 boolean iterateThroughList = false;
463 if (iterateThroughList && logger.isDebugEnabled()) {
464 List<CollectionobjectsCommonList.CollectionObjectListItem> items =
465 list.getCollectionObjectListItem();
468 for (CollectionobjectsCommonList.CollectionObjectListItem item : items) {
469 logger.debug(testName + ": list-item[" + i + "] csid="
471 logger.debug(testName + ": list-item[" + i + "] objectNumber="
472 + item.getObjectNumber());
473 logger.debug(testName + ": list-item[" + i + "] URI="
483 // ---------------------------------------------------------------
484 // CRUD tests : UPDATE tests
485 // ---------------------------------------------------------------
488 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
489 dependsOnMethods = {"read"})
490 public void update(String testName) throws Exception {
493 setupUpdate(testName);
495 // Read an existing resource that will be updated.
496 ClientResponse<MultipartInput> res = updateRetrieve(testName, knownResourceId);
498 // Extract its common part.
499 MultipartInput input = (MultipartInput) res.getEntity();
500 CollectionobjectsCommon collectionObject =
501 (CollectionobjectsCommon) extractPart(input,
502 client.getCommonPartName(), CollectionobjectsCommon.class);
503 Assert.assertNotNull(collectionObject);
505 // Change the content of one or more fields in the common part.
506 collectionObject.setObjectNumber("updated-" + collectionObject.getObjectNumber());
507 collectionObject.setObjectName("updated-" + collectionObject.getObjectName());
508 if (logger.isDebugEnabled()) {
509 logger.debug("sparse update that will be sent in update request:");
510 logger.debug(objectAsXmlString(collectionObject,
511 CollectionobjectsCommon.class));
514 // Send the changed resource to be updated.
515 res = updateSend(testName, knownResourceId, collectionObject);
516 int statusCode = res.getStatus();
517 // Check the status code of the response: does it match the expected response(s)?
518 if (logger.isDebugEnabled()) {
519 logger.debug(testName + ": status = " + statusCode);
521 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
522 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
523 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
525 // Read the response and verify that the resource was correctly updated.
526 input = (MultipartInput) res.getEntity();
527 CollectionobjectsCommon updatedCollectionObject =
528 (CollectionobjectsCommon) extractPart(input,
529 client.getCommonPartName(), CollectionobjectsCommon.class);
530 Assert.assertNotNull(updatedCollectionObject);
531 Assert.assertEquals(updatedCollectionObject.getObjectName(),
532 collectionObject.getObjectName(),
533 "Data in updated object did not match submitted data.");
537 private ClientResponse<MultipartInput> updateRetrieve(String testName, String id) {
538 final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
539 ClientResponse<MultipartInput> res = client.read(id);
540 if (logger.isDebugEnabled()) {
541 logger.debug("read in updateRetrieve for " + testName + " status = " + res.getStatus());
543 Assert.assertEquals(res.getStatus(), EXPECTED_STATUS);
544 if (logger.isDebugEnabled()) {
545 logger.debug("got object to updateRetrieve for " + testName + " with ID: " + id);
550 private ClientResponse<MultipartInput> updateSend(String testName, String id,
551 CollectionobjectsCommon collectionObject) {
552 MultipartOutput output = new MultipartOutput();
553 OutputPart commonPart = output.addPart(collectionObject, MediaType.APPLICATION_XML_TYPE);
554 commonPart.getHeaders().add("label", client.getCommonPartName());
555 ClientResponse<MultipartInput> res = client.update(knownResourceId, output);
560 // Placeholders until the three tests below can be uncommented.
561 // See Issue CSPACE-401.
563 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
564 dependsOnMethods = {"read"})
565 public void updateWithEmptyEntityBody(String testName) throws Exception {
569 * Test how the service handles XML that is not well formed,
570 * when sent in the payload of an Update request.
572 * @param testName The name of this test method. This name is supplied
573 * automatically, via reflection, by a TestNG 'data provider' in
577 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
578 dependsOnMethods = {"read"})
579 public void updateWithMalformedXml(String testName) throws Exception {
583 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
584 dependsOnMethods = {"read"})
585 public void updateWithWrongXmlSchema(String testName) throws Exception {
590 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
591 dependsOnMethods = {"create", "update", "testSubmitRequest"})
592 public void updateWithEmptyEntityBody(String testName) throws Exception {
595 setupUpdateWithEmptyEntityBody(testName);
597 // Submit the request to the service and store the response.
598 String method = REQUEST_TYPE.httpMethodName();
599 String url = getResourceURL(knownResourceId);
600 String mediaType = MediaType.APPLICATION_XML;
601 final String entity = "";
602 int statusCode = submitRequest(method, url, mediaType, entity);
604 // Check the status code of the response: does it match
605 // the expected response(s)?
606 if(logger.isDebugEnabled()){
607 logger.debug(testName + ": url=" + url +
608 " status=" + statusCode);
610 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
611 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
612 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
616 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
617 dependsOnMethods = {"create", "update", "testSubmitRequest"})
618 public void updateWithMalformedXml() throws Exception {
621 setupUpdateWithMalformedXml(testName);
623 // Submit the request to the service and store the response.
624 String method = REQUEST_TYPE.httpMethodName();
625 String url = getResourceURL(knownResourceId);
626 final String entity = MALFORMED_XML_DATA;
627 String mediaType = MediaType.APPLICATION_XML;
628 int statusCode = submitRequest(method, url, mediaType, entity);
630 // Check the status code of the response: does it match
631 // the expected response(s)?
632 if(logger.isDebugEnabled()){
633 logger.debug(testName + ": url=" + url +
634 " status=" + statusCode);
636 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
637 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
638 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
642 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
643 dependsOnMethods = {"create", "update", "testSubmitRequest"})
644 public void updateWithWrongXmlSchema(String testName) throws Exception {
647 setupUpdateWithWrongXmlSchema(String testName);
649 // Submit the request to the service and store the response.
650 String method = REQUEST_TYPE.httpMethodName();
651 String url = getResourceURL(knownResourceId);
652 String mediaType = MediaType.APPLICATION_XML;
653 final String entity = WRONG_XML_SCHEMA_DATA;
654 int statusCode = submitRequest(method, url, mediaType, entity);
656 // Check the status code of the response: does it match
657 // the expected response(s)?
658 if(logger.isDebugEnabled()){
659 logger.debug(testName + ": url=" + url +
660 " status=" + statusCode);
662 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
663 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
664 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
669 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
670 dependsOnMethods = {"update", "testSubmitRequest"})
671 public void updateNonExistent(String testName) throws Exception {
674 setupUpdateNonExistent(testName);
676 // Submit the request to the service and store the response.
678 // Note: The ID used in this 'create' call may be arbitrary.
679 // The only relevant ID may be the one used in updateCollectionObject(), below.
680 MultipartOutput multipart =
681 createCollectionObjectInstance(client.getCommonPartName(),
683 ClientResponse<MultipartInput> res =
684 client.update(NON_EXISTENT_ID, multipart);
685 int statusCode = res.getStatus();
687 // Check the status code of the response: does it match
688 // the expected response(s)?
689 if (logger.isDebugEnabled()) {
690 logger.debug(testName + ": status = " + statusCode);
692 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
693 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
694 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
698 * Test how the service handles, in an Update request, payloads
699 * containing null values (or, in the case of String fields,
700 * empty String values) in one or more fields in which non-empty
701 * values are required.
703 * This is a test of code and/or configuration in the service's
704 * validation routine(s).
706 * @param testName The name of this test method. This name is supplied
707 * automatically, via reflection, by a TestNG 'data provider' in
710 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
711 dependsOnMethods = {"read"})
712 public void updateWithRequiredValuesNullOrEmpty(String testName) throws Exception {
714 setupUpdate(testName);
715 if (logger.isDebugEnabled()) {
716 logger.debug(testName + " got object to update with ID: " + knownResourceId);
719 // Read an existing record for updating.
720 ClientResponse<MultipartInput> res = updateRetrieve(testName, knownResourceId);
722 MultipartInput input = (MultipartInput) res.getEntity();
723 CollectionobjectsCommon collectionObject =
724 (CollectionobjectsCommon) extractPart(input,
725 client.getCommonPartName(), CollectionobjectsCommon.class);
726 Assert.assertNotNull(collectionObject);
728 // Update with invalid content, by setting a value to the
729 // empty String, in a field that requires a non-empty value,
730 // as enforced by the service's validation routine(s).
731 collectionObject.setObjectNumber("");
733 if (logger.isDebugEnabled()) {
734 logger.debug(testName + " updated object");
735 logger.debug(objectAsXmlString(collectionObject,
736 CollectionobjectsCommon.class));
739 // Submit the request to the service and store the response.
740 res = updateSend(testName, knownResourceId, collectionObject);
741 int statusCode = res.getStatus();
743 // Read the response and verify that the update attempt failed.
744 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
745 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
746 Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
750 // ---------------------------------------------------------------
751 // CRUD tests : DELETE tests
752 // ---------------------------------------------------------------
755 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
756 dependsOnMethods = {"create", "readList", "testSubmitRequest", "update"})
757 public void delete(String testName) throws Exception {
760 setupDelete(testName);
762 // Submit the request to the service and store the response.
763 ClientResponse<Response> res = client.delete(knownResourceId);
764 int statusCode = res.getStatus();
766 // Check the status code of the response: does it match
767 // the expected response(s)?
768 if (logger.isDebugEnabled()) {
769 logger.debug(testName + ": status = " + statusCode);
771 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
772 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
773 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
778 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
779 dependsOnMethods = {"delete"})
780 public void deleteNonExistent(String testName) throws Exception {
783 setupDeleteNonExistent(testName);
785 // Submit the request to the service and store the response.
786 ClientResponse<Response> res = client.delete(NON_EXISTENT_ID);
787 int statusCode = res.getStatus();
789 // Check the status code of the response: does it match
790 // the expected response(s)?
791 if (logger.isDebugEnabled()) {
792 logger.debug(testName + ": status = " + statusCode);
794 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
795 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
796 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
799 // ---------------------------------------------------------------
800 // Utility tests : tests of code used in tests above
801 // ---------------------------------------------------------------
803 * Tests the code for manually submitting data that is used by several
804 * of the methods above.
807 @Test(dependsOnMethods = {"create", "read"})
808 public void testSubmitRequest() throws Exception {
809 testSubmitRequest(knownResourceId);
812 private void testSubmitRequest(String resourceId) throws Exception {
814 // Expected status code: 200 OK
815 final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
817 // Submit the request to the service and store the response.
818 String method = ServiceRequestType.READ.httpMethodName();
819 String url = getResourceURL(resourceId);
820 int statusCode = submitRequest(method, url);
822 // Check the status code of the response: does it match
823 // the expected response(s)?
824 if (logger.isDebugEnabled()) {
825 logger.debug("testSubmitRequest: url=" + url
826 + " status=" + statusCode);
828 Assert.assertEquals(statusCode, EXPECTED_STATUS);
832 // ---------------------------------------------------------------
833 // Cleanup of resources created during testing
834 // ---------------------------------------------------------------
836 * Deletes all resources created by tests, after all tests have been run.
838 * This cleanup method will always be run, even if one or more tests fail.
839 * For this reason, it attempts to remove all resources created
840 * at any point during testing, even if some of those resources
841 * may be expected to be deleted by certain tests.
843 @AfterClass(alwaysRun = true)
844 public void cleanUp() {
845 if (logger.isDebugEnabled()) {
846 logger.debug("Cleaning up temporary resources created for testing ...");
848 for (String resourceId : allResourceIdsCreated) {
849 // Note: Any non-success responses are ignored and not reported.
850 ClientResponse<Response> res = client.delete(resourceId);
854 // ---------------------------------------------------------------
855 // Utility methods used by tests above
856 // ---------------------------------------------------------------
857 private MultipartOutput createCollectionObjectInstance(String commonPartName,
859 return createCollectionObjectInstance(commonPartName,
860 "objectNumber-" + identifier,
861 "objectName-" + identifier);
864 private MultipartOutput createCollectionObjectInstance(String commonPartName,
865 String objectNumber, String objectName) {
866 CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
867 ResponsibleDepartmentList deptList = new ResponsibleDepartmentList();
868 List<String> depts = deptList.getResponsibleDepartment();
869 // @TODO Use properly formatted refNames for representative departments
870 // in this example test record. The following are mere placeholders.
871 depts.add("urn:org.collectionspace.services.department:Registrar");
873 depts.add("urn:org.walkerart.department:Fine Art");
875 multivalue = !multivalue;
876 //FIXME: Title does not need to be set.
877 collectionObject.setTitle("atitle");
878 collectionObject.setResponsibleDepartments(deptList);
879 collectionObject.setObjectNumber(objectNumber);
880 collectionObject.setOtherNumber("urn:org.walkerart.id:123");
881 collectionObject.setObjectName(objectName);
882 collectionObject.setAge(""); //test for null string
883 collectionObject.setBriefDescription("Papier mache bird cow mask with horns, "
884 + "painted red with black and yellow spots. "
885 + "Puerto Rico. ca. 8" high, 6" wide, projects 10" (with horns).");
887 CollectionobjectsNaturalhistory conh = new CollectionobjectsNaturalhistory();
888 conh.setNhString("test-string");
890 conh.setNhLong(9999);
893 MultipartOutput multipart = createCollectionObjectInstance(commonPartName, collectionObject, conh);
897 private MultipartOutput createCollectionObjectInstance(String commonPartName,
898 CollectionobjectsCommon collectionObject, CollectionobjectsNaturalhistory conh) {
900 MultipartOutput multipart = new MultipartOutput();
901 OutputPart commonPart = multipart.addPart(collectionObject,
902 MediaType.APPLICATION_XML_TYPE);
903 commonPart.getHeaders().add("label", commonPartName);
905 if (logger.isDebugEnabled()) {
906 logger.debug("to be created, collectionobject common");
907 logger.debug(objectAsXmlString(collectionObject,
908 CollectionobjectsCommon.class));
912 OutputPart nhPart = multipart.addPart(conh, MediaType.APPLICATION_XML_TYPE);
913 nhPart.getHeaders().add("label", getNHPartName());
915 if (logger.isDebugEnabled()) {
916 logger.debug("to be created, collectionobject nhistory");
917 logger.debug(objectAsXmlString(conh,
918 CollectionobjectsNaturalhistory.class));
926 * createCollectionObjectInstanceFromXml uses JAXB unmarshaller to retrieve
927 * collectionobject from given file
928 * @param commonPartName
929 * @param commonPartFileName
933 private MultipartOutput createCollectionObjectInstanceFromXml(String testName, String commonPartName,
934 String commonPartFileName) throws Exception {
936 CollectionobjectsCommon collectionObject =
937 (CollectionobjectsCommon) getObjectFromFile(CollectionobjectsCommon.class,
939 MultipartOutput multipart = new MultipartOutput();
940 OutputPart commonPart = multipart.addPart(collectionObject,
941 MediaType.APPLICATION_XML_TYPE);
942 commonPart.getHeaders().add("label", commonPartName);
944 if (logger.isDebugEnabled()) {
945 logger.debug(testName + " to be created, collectionobject common");
946 logger.debug(objectAsXmlString(collectionObject,
947 CollectionobjectsCommon.class));
954 * createCollectionObjectInstanceFromRawXml uses stringified collectionobject
955 * retrieve from given file
956 * @param commonPartName
957 * @param commonPartFileName
961 private MultipartOutput createCollectionObjectInstanceFromRawXml(String testName, String commonPartName,
962 String commonPartFileName) throws Exception {
964 MultipartOutput multipart = new MultipartOutput();
965 String stringObject = getXmlDocumentAsString(commonPartFileName);
966 if (logger.isDebugEnabled()) {
967 logger.debug(testName + " to be created, collectionobject common " + "\n" + stringObject);
969 OutputPart commonPart = multipart.addPart(stringObject,
970 MediaType.APPLICATION_XML_TYPE);
971 commonPart.getHeaders().add("label", commonPartName);
977 private String getNHPartName() {
978 return "collectionobjects_naturalhistory";
981 private String createFromXmlFile(String testName, String fileName, boolean useJaxb) throws Exception {
982 // Perform setup, such as initializing the type of service request
983 // (e.g. CREATE, DELETE), its valid and expected status codes, and
984 // its associated HTTP method name (e.g. POST, DELETE).
985 setupCreate(testName);
987 MultipartOutput multipart = null;
990 multipart = createCollectionObjectInstanceFromXml(testName,
991 client.getCommonPartName(), fileName);
993 multipart = createCollectionObjectInstanceFromRawXml(testName,
994 client.getCommonPartName(), fileName);
996 ClientResponse<Response> res = client.create(multipart);
997 int statusCode = res.getStatus();
999 if (logger.isDebugEnabled()) {
1000 logger.debug(testName + ": status = " + statusCode);
1002 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
1003 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
1004 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
1005 String newId = extractId(res);
1006 allResourceIdsCreated.add(newId);