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 String knownResourceId = null;
60 private List<String> allResourceIdsCreated = new ArrayList();
61 private boolean multivalue; //toggle
64 * This method is called only by the parent class, AbstractServiceTest
67 protected String getServicePathComponent() {
68 return new CollectionObjectClient().getServicePathComponent();
71 // ---------------------------------------------------------------
72 // CRUD tests : CREATE tests
73 // ---------------------------------------------------------------
76 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
77 public void create(String testName) throws Exception {
79 // Perform setup, such as initializing the type of service request
80 // (e.g. CREATE, DELETE), its valid and expected status codes, and
81 // its associated HTTP method name (e.g. POST, DELETE).
82 setupCreate(testName);
84 // Submit the request to the service and store the response.
85 CollectionObjectClient client = new CollectionObjectClient();
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 CollectionObjectClient client = new CollectionObjectClient();
329 MultipartOutput multipart =
330 createCollectionObjectInstance(client.getCommonPartName(), collectionObject, null);
331 ClientResponse<Response> res = client.create(multipart);
332 int statusCode = res.getStatus();
334 // Read the response and verify that the create attempt failed.
335 if (logger.isDebugEnabled()) {
336 logger.debug(testName + ": status = " + statusCode);
338 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
339 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
340 Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
342 // FIXME: Consider splitting off the following into its own test method.
344 // Build a payload with invalid content, by setting a value to the
345 // empty String, in a field that requires a non-empty value,
346 // as enforced by the service's validation routine(s).
347 collectionObject = new CollectionobjectsCommon();
348 collectionObject.setTitle("atitle");
349 collectionObject.setObjectName("some name");
350 collectionObject.setObjectNumber("");
352 // Submit the request to the service and store the response.
354 createCollectionObjectInstance(client.getCommonPartName(), collectionObject, null);
355 res = client.create(multipart);
356 statusCode = res.getStatus();
358 // Read the response and verify that the create attempt failed.
359 if (logger.isDebugEnabled()) {
360 logger.debug(testName + ": status = " + statusCode);
362 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
363 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
364 Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
369 // ---------------------------------------------------------------
370 // CRUD tests : READ tests
371 // ---------------------------------------------------------------
374 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
375 dependsOnMethods = {"create"})
376 public void read(String testName) throws Exception {
381 // Submit the request to the service and store the response.
382 CollectionObjectClient client = new CollectionObjectClient();
383 ClientResponse<MultipartInput> res = client.read(knownResourceId);
384 int statusCode = res.getStatus();
386 // Check the status code of the response: does it match
387 // the expected response(s)?
388 if (logger.isDebugEnabled()) {
389 logger.debug(testName + ": status = " + statusCode);
391 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
392 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
393 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
395 MultipartInput input = (MultipartInput) res.getEntity();
397 if (logger.isDebugEnabled()) {
398 logger.debug(testName + ": Reading Common part ...");
400 CollectionobjectsCommon collectionObject =
401 (CollectionobjectsCommon) extractPart(input,
402 client.getCommonPartName(), CollectionobjectsCommon.class);
403 Assert.assertNotNull(collectionObject);
405 if (logger.isDebugEnabled()) {
406 logger.debug(testName + ": Reading Natural History part ...");
408 CollectionobjectsNaturalhistory conh =
409 (CollectionobjectsNaturalhistory) extractPart(input,
410 getNHPartName(), CollectionobjectsNaturalhistory.class);
411 Assert.assertNotNull(conh);
416 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
417 dependsOnMethods = {"read"})
418 public void readNonExistent(String testName) throws Exception {
421 setupReadNonExistent(testName);
423 // Submit the request to the service and store the response.
424 CollectionObjectClient client = new CollectionObjectClient();
425 ClientResponse<MultipartInput> res = client.read(NON_EXISTENT_ID);
426 int statusCode = res.getStatus();
428 // Check the status code of the response: does it match
429 // the expected response(s)?
430 if (logger.isDebugEnabled()) {
431 logger.debug(testName + ": status = " + statusCode);
433 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
434 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
435 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
438 // ---------------------------------------------------------------
439 // CRUD tests : READ_LIST tests
440 // ---------------------------------------------------------------
443 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
444 dependsOnMethods = {"createList", "read"})
445 public void readList(String testName) throws Exception {
448 setupReadList(testName);
450 // Submit the request to the service and store the response.
451 CollectionObjectClient client = new CollectionObjectClient();
452 ClientResponse<CollectionobjectsCommonList> res = client.readList();
453 CollectionobjectsCommonList list = res.getEntity();
454 int statusCode = res.getStatus();
456 // Check the status code of the response: does it match
457 // the expected response(s)?
458 if (logger.isDebugEnabled()) {
459 logger.debug(testName + ": status = " + statusCode);
461 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
462 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
463 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
465 // Optionally output additional data about list members for debugging.
466 boolean iterateThroughList = false;
467 if (iterateThroughList && logger.isDebugEnabled()) {
468 List<CollectionobjectsCommonList.CollectionObjectListItem> items =
469 list.getCollectionObjectListItem();
472 for (CollectionobjectsCommonList.CollectionObjectListItem item : items) {
473 logger.debug(testName + ": list-item[" + i + "] csid="
475 logger.debug(testName + ": list-item[" + i + "] objectNumber="
476 + item.getObjectNumber());
477 logger.debug(testName + ": list-item[" + i + "] URI="
487 // ---------------------------------------------------------------
488 // CRUD tests : UPDATE tests
489 // ---------------------------------------------------------------
492 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
493 dependsOnMethods = {"read"})
494 public void update(String testName) throws Exception {
497 setupUpdate(testName);
499 // Read an existing resource that will be updated.
500 ClientResponse<MultipartInput> res = updateRetrieve(testName, knownResourceId);
502 // Extract its common part.
503 CollectionObjectClient client = new CollectionObjectClient();
504 MultipartInput input = (MultipartInput) res.getEntity();
505 CollectionobjectsCommon collectionObject =
506 (CollectionobjectsCommon) extractPart(input,
507 client.getCommonPartName(), CollectionobjectsCommon.class);
508 Assert.assertNotNull(collectionObject);
510 // Change the content of one or more fields in the common part.
511 collectionObject.setObjectNumber("updated-" + collectionObject.getObjectNumber());
512 collectionObject.setObjectName("updated-" + collectionObject.getObjectName());
513 if (logger.isDebugEnabled()) {
514 logger.debug("sparse update that will be sent in update request:");
515 logger.debug(objectAsXmlString(collectionObject,
516 CollectionobjectsCommon.class));
519 // Send the changed resource to be updated.
520 res = updateSend(testName, knownResourceId, collectionObject);
521 int statusCode = res.getStatus();
522 // Check the status code of the response: does it match the expected response(s)?
523 if (logger.isDebugEnabled()) {
524 logger.debug(testName + ": status = " + statusCode);
526 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
527 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
528 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
530 // Read the response and verify that the resource was correctly updated.
531 input = (MultipartInput) res.getEntity();
532 CollectionobjectsCommon updatedCollectionObject =
533 (CollectionobjectsCommon) extractPart(input,
534 client.getCommonPartName(), CollectionobjectsCommon.class);
535 Assert.assertNotNull(updatedCollectionObject);
536 Assert.assertEquals(updatedCollectionObject.getObjectName(),
537 collectionObject.getObjectName(),
538 "Data in updated object did not match submitted data.");
542 private ClientResponse<MultipartInput> updateRetrieve(String testName, String id) {
543 final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
544 CollectionObjectClient client = new CollectionObjectClient();
545 ClientResponse<MultipartInput> res = client.read(id);
546 if (logger.isDebugEnabled()) {
547 logger.debug("read in updateRetrieve for " + testName + " status = " + res.getStatus());
549 Assert.assertEquals(res.getStatus(), EXPECTED_STATUS);
550 if (logger.isDebugEnabled()) {
551 logger.debug("got object to updateRetrieve for " + testName + " with ID: " + id);
556 private ClientResponse<MultipartInput> updateSend(String testName, String id,
557 CollectionobjectsCommon collectionObject) {
558 MultipartOutput output = new MultipartOutput();
559 OutputPart commonPart = output.addPart(collectionObject, MediaType.APPLICATION_XML_TYPE);
560 CollectionObjectClient client = new CollectionObjectClient();
561 commonPart.getHeaders().add("label", client.getCommonPartName());
562 ClientResponse<MultipartInput> res = client.update(knownResourceId, output);
567 // Placeholders until the three tests below can be uncommented.
568 // See Issue CSPACE-401.
570 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
571 dependsOnMethods = {"read"})
572 public void updateWithEmptyEntityBody(String testName) throws Exception {
576 * Test how the service handles XML that is not well formed,
577 * when sent in the payload of an Update request.
579 * @param testName The name of this test method. This name is supplied
580 * automatically, via reflection, by a TestNG 'data provider' in
584 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
585 dependsOnMethods = {"read"})
586 public void updateWithMalformedXml(String testName) throws Exception {
590 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
591 dependsOnMethods = {"read"})
592 public void updateWithWrongXmlSchema(String testName) throws Exception {
597 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
598 dependsOnMethods = {"create", "update", "testSubmitRequest"})
599 public void updateWithEmptyEntityBody(String testName) throws Exception {
602 setupUpdateWithEmptyEntityBody(testName);
604 // Submit the request to the service and store the response.
605 String method = REQUEST_TYPE.httpMethodName();
606 String url = getResourceURL(knownResourceId);
607 String mediaType = MediaType.APPLICATION_XML;
608 final String entity = "";
609 int statusCode = submitRequest(method, url, mediaType, entity);
611 // Check the status code of the response: does it match
612 // the expected response(s)?
613 if(logger.isDebugEnabled()){
614 logger.debug(testName + ": url=" + url +
615 " status=" + statusCode);
617 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
618 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
619 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
623 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
624 dependsOnMethods = {"create", "update", "testSubmitRequest"})
625 public void updateWithMalformedXml() throws Exception {
628 setupUpdateWithMalformedXml(testName);
630 // Submit the request to the service and store the response.
631 String method = REQUEST_TYPE.httpMethodName();
632 String url = getResourceURL(knownResourceId);
633 final String entity = MALFORMED_XML_DATA;
634 String mediaType = MediaType.APPLICATION_XML;
635 int statusCode = submitRequest(method, url, mediaType, entity);
637 // Check the status code of the response: does it match
638 // the expected response(s)?
639 if(logger.isDebugEnabled()){
640 logger.debug(testName + ": url=" + url +
641 " status=" + statusCode);
643 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
644 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
645 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
649 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
650 dependsOnMethods = {"create", "update", "testSubmitRequest"})
651 public void updateWithWrongXmlSchema(String testName) throws Exception {
654 setupUpdateWithWrongXmlSchema(String testName);
656 // Submit the request to the service and store the response.
657 String method = REQUEST_TYPE.httpMethodName();
658 String url = getResourceURL(knownResourceId);
659 String mediaType = MediaType.APPLICATION_XML;
660 final String entity = WRONG_XML_SCHEMA_DATA;
661 int statusCode = submitRequest(method, url, mediaType, entity);
663 // Check the status code of the response: does it match
664 // the expected response(s)?
665 if(logger.isDebugEnabled()){
666 logger.debug(testName + ": url=" + url +
667 " status=" + statusCode);
669 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
670 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
671 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
676 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
677 dependsOnMethods = {"update", "testSubmitRequest"})
678 public void updateNonExistent(String testName) throws Exception {
681 setupUpdateNonExistent(testName);
683 // Submit the request to the service and store the response.
685 // Note: The ID used in this 'create' call may be arbitrary.
686 // The only relevant ID may be the one used in updateCollectionObject(), below.
687 CollectionObjectClient client = new CollectionObjectClient();
688 MultipartOutput multipart =
689 createCollectionObjectInstance(client.getCommonPartName(),
691 ClientResponse<MultipartInput> res =
692 client.update(NON_EXISTENT_ID, multipart);
693 int statusCode = res.getStatus();
695 // Check the status code of the response: does it match
696 // the expected response(s)?
697 if (logger.isDebugEnabled()) {
698 logger.debug(testName + ": status = " + statusCode);
700 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
701 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
702 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
706 * Test how the service handles, in an Update request, payloads
707 * containing null values (or, in the case of String fields,
708 * empty String values) in one or more fields in which non-empty
709 * values are required.
711 * This is a test of code and/or configuration in the service's
712 * validation routine(s).
714 * @param testName The name of this test method. This name is supplied
715 * automatically, via reflection, by a TestNG 'data provider' in
718 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
719 dependsOnMethods = {"read"})
720 public void updateWithRequiredValuesNullOrEmpty(String testName) throws Exception {
722 setupUpdate(testName);
723 if (logger.isDebugEnabled()) {
724 logger.debug(testName + " got object to update with ID: " + knownResourceId);
727 // Read an existing record for updating.
728 ClientResponse<MultipartInput> res = updateRetrieve(testName, knownResourceId);
730 CollectionObjectClient client = new CollectionObjectClient();
731 MultipartInput input = (MultipartInput) res.getEntity();
732 CollectionobjectsCommon collectionObject =
733 (CollectionobjectsCommon) extractPart(input,
734 client.getCommonPartName(), CollectionobjectsCommon.class);
735 Assert.assertNotNull(collectionObject);
737 // Update with invalid content, by setting a value to the
738 // empty String, in a field that requires a non-empty value,
739 // as enforced by the service's validation routine(s).
740 collectionObject.setObjectNumber("");
742 if (logger.isDebugEnabled()) {
743 logger.debug(testName + " updated object");
744 logger.debug(objectAsXmlString(collectionObject,
745 CollectionobjectsCommon.class));
748 // Submit the request to the service and store the response.
749 res = updateSend(testName, knownResourceId, collectionObject);
750 int statusCode = res.getStatus();
752 // Read the response and verify that the update attempt failed.
753 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
754 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
755 Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
759 // ---------------------------------------------------------------
760 // CRUD tests : DELETE tests
761 // ---------------------------------------------------------------
764 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
765 dependsOnMethods = {"create", "readList", "testSubmitRequest", "update"})
766 public void delete(String testName) throws Exception {
769 setupDelete(testName);
771 // Submit the request to the service and store the response.
772 CollectionObjectClient client = new CollectionObjectClient();
773 ClientResponse<Response> res = client.delete(knownResourceId);
774 int statusCode = res.getStatus();
776 // Check the status code of the response: does it match
777 // the expected response(s)?
778 if (logger.isDebugEnabled()) {
779 logger.debug(testName + ": status = " + statusCode);
781 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
782 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
783 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
788 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
789 dependsOnMethods = {"delete"})
790 public void deleteNonExistent(String testName) throws Exception {
793 setupDeleteNonExistent(testName);
795 // Submit the request to the service and store the response.
796 CollectionObjectClient client = new CollectionObjectClient();
797 ClientResponse<Response> res = client.delete(NON_EXISTENT_ID);
798 int statusCode = res.getStatus();
800 // Check the status code of the response: does it match
801 // the expected response(s)?
802 if (logger.isDebugEnabled()) {
803 logger.debug(testName + ": status = " + statusCode);
805 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
806 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
807 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
810 // ---------------------------------------------------------------
811 // Utility tests : tests of code used in tests above
812 // ---------------------------------------------------------------
814 * Tests the code for manually submitting data that is used by several
815 * of the methods above.
818 @Test(dependsOnMethods = {"create", "read"})
819 public void testSubmitRequest() throws Exception {
820 testSubmitRequest(knownResourceId);
823 private void testSubmitRequest(String resourceId) throws Exception {
825 // Expected status code: 200 OK
826 final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
828 // Submit the request to the service and store the response.
829 String method = ServiceRequestType.READ.httpMethodName();
830 String url = getResourceURL(resourceId);
831 int statusCode = submitRequest(method, url);
833 // Check the status code of the response: does it match
834 // the expected response(s)?
835 if (logger.isDebugEnabled()) {
836 logger.debug("testSubmitRequest: url=" + url
837 + " status=" + statusCode);
839 Assert.assertEquals(statusCode, EXPECTED_STATUS);
843 // ---------------------------------------------------------------
844 // Cleanup of resources created during testing
845 // ---------------------------------------------------------------
847 * Deletes all resources created by tests, after all tests have been run.
849 * This cleanup method will always be run, even if one or more tests fail.
850 * For this reason, it attempts to remove all resources created
851 * at any point during testing, even if some of those resources
852 * may be expected to be deleted by certain tests.
854 @AfterClass(alwaysRun = true)
855 public void cleanUp() {
856 if (logger.isDebugEnabled()) {
857 logger.debug("Cleaning up temporary resources created for testing ...");
859 CollectionObjectClient client = new CollectionObjectClient();
860 for (String resourceId : allResourceIdsCreated) {
861 // Note: Any non-success responses are ignored and not reported.
862 ClientResponse<Response> res = client.delete(resourceId);
866 // ---------------------------------------------------------------
867 // Utility methods used by tests above
868 // ---------------------------------------------------------------
869 private MultipartOutput createCollectionObjectInstance(String commonPartName,
871 return createCollectionObjectInstance(commonPartName,
872 "objectNumber-" + identifier,
873 "objectName-" + identifier);
876 private MultipartOutput createCollectionObjectInstance(String commonPartName,
877 String objectNumber, String objectName) {
878 CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
879 ResponsibleDepartmentList deptList = new ResponsibleDepartmentList();
880 List<String> depts = deptList.getResponsibleDepartment();
881 // @TODO Use properly formatted refNames for representative departments
882 // in this example test record. The following are mere placeholders.
883 depts.add("urn:org.collectionspace.services.department:Registrar");
885 depts.add("urn:org.walkerart.department:Fine Art");
887 multivalue = !multivalue;
888 //FIXME: Title does not need to be set.
889 collectionObject.setTitle("atitle");
890 collectionObject.setResponsibleDepartments(deptList);
891 collectionObject.setObjectNumber(objectNumber);
892 collectionObject.setOtherNumber("urn:org.walkerart.id:123");
893 collectionObject.setObjectName(objectName);
894 collectionObject.setAge(""); //test for null string
895 collectionObject.setBriefDescription("Papier mache bird cow mask with horns, "
896 + "painted red with black and yellow spots. "
897 + "Puerto Rico. ca. 8" high, 6" wide, projects 10" (with horns).");
899 CollectionobjectsNaturalhistory conh = new CollectionobjectsNaturalhistory();
900 conh.setNhString("test-string");
902 conh.setNhLong(9999);
905 MultipartOutput multipart = createCollectionObjectInstance(commonPartName, collectionObject, conh);
909 private MultipartOutput createCollectionObjectInstance(String commonPartName,
910 CollectionobjectsCommon collectionObject, CollectionobjectsNaturalhistory conh) {
912 MultipartOutput multipart = new MultipartOutput();
913 OutputPart commonPart = multipart.addPart(collectionObject,
914 MediaType.APPLICATION_XML_TYPE);
915 commonPart.getHeaders().add("label", commonPartName);
917 if (logger.isDebugEnabled()) {
918 logger.debug("to be created, collectionobject common");
919 logger.debug(objectAsXmlString(collectionObject,
920 CollectionobjectsCommon.class));
924 OutputPart nhPart = multipart.addPart(conh, MediaType.APPLICATION_XML_TYPE);
925 nhPart.getHeaders().add("label", getNHPartName());
927 if (logger.isDebugEnabled()) {
928 logger.debug("to be created, collectionobject nhistory");
929 logger.debug(objectAsXmlString(conh,
930 CollectionobjectsNaturalhistory.class));
938 * createCollectionObjectInstanceFromXml uses JAXB unmarshaller to retrieve
939 * collectionobject from given file
940 * @param commonPartName
941 * @param commonPartFileName
945 private MultipartOutput createCollectionObjectInstanceFromXml(String testName, String commonPartName,
946 String commonPartFileName) throws Exception {
948 CollectionobjectsCommon collectionObject =
949 (CollectionobjectsCommon) getObjectFromFile(CollectionobjectsCommon.class,
951 MultipartOutput multipart = new MultipartOutput();
952 OutputPart commonPart = multipart.addPart(collectionObject,
953 MediaType.APPLICATION_XML_TYPE);
954 commonPart.getHeaders().add("label", commonPartName);
956 if (logger.isDebugEnabled()) {
957 logger.debug(testName + " to be created, collectionobject common");
958 logger.debug(objectAsXmlString(collectionObject,
959 CollectionobjectsCommon.class));
966 * createCollectionObjectInstanceFromRawXml uses stringified collectionobject
967 * retrieve from given file
968 * @param commonPartName
969 * @param commonPartFileName
973 private MultipartOutput createCollectionObjectInstanceFromRawXml(String testName, String commonPartName,
974 String commonPartFileName) throws Exception {
976 MultipartOutput multipart = new MultipartOutput();
977 String stringObject = getXmlDocumentAsString(commonPartFileName);
978 if (logger.isDebugEnabled()) {
979 logger.debug(testName + " to be created, collectionobject common " + "\n" + stringObject);
981 OutputPart commonPart = multipart.addPart(stringObject,
982 MediaType.APPLICATION_XML_TYPE);
983 commonPart.getHeaders().add("label", commonPartName);
989 private String getNHPartName() {
990 return "collectionobjects_naturalhistory";
993 private String createFromXmlFile(String testName, String fileName, boolean useJaxb) throws Exception {
994 // Perform setup, such as initializing the type of service request
995 // (e.g. CREATE, DELETE), its valid and expected status codes, and
996 // its associated HTTP method name (e.g. POST, DELETE).
997 setupCreate(testName);
999 MultipartOutput multipart = null;
1001 CollectionObjectClient client = new CollectionObjectClient();
1003 multipart = createCollectionObjectInstanceFromXml(testName,
1004 client.getCommonPartName(), fileName);
1006 multipart = createCollectionObjectInstanceFromRawXml(testName,
1007 client.getCommonPartName(), fileName);
1009 ClientResponse<Response> res = client.create(multipart);
1010 int statusCode = res.getStatus();
1012 if (logger.isDebugEnabled()) {
1013 logger.debug(testName + ": status = " + statusCode);
1015 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
1016 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
1017 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
1018 String newId = extractId(res);
1019 allResourceIdsCreated.add(newId);