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 {
135 String testDataDir = System.getProperty("test-data.fileName");
137 //createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp1.xml", false);
138 createFromXmlFile(testName, testDataDir + "/repfield_whitesp1.xml", false);
139 testSubmitRequest(newId);
142 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
143 dependsOnMethods = {"create", "testSubmitRequest"})
144 public void createFromXmlRFWS2(String testName) throws Exception {
145 String testDataDir = System.getProperty("test-data.fileName");
147 //createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp2.xml", false);
148 createFromXmlFile(testName, testDataDir + "/repfield_whitesp2.xml", false);
149 testSubmitRequest(newId);
152 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
153 dependsOnMethods = {"create", "testSubmitRequest"})
154 public void createFromXmlRFWS3(String testName) throws Exception {
155 String testDataDir = System.getProperty("test-data.fileName");
157 //createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp3.xml", false);
158 createFromXmlFile(testName, testDataDir + "/repfield_whitesp3.xml", false);
159 testSubmitRequest(newId);
162 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
163 dependsOnMethods = {"create", "testSubmitRequest"})
164 public void createFromXmlRFWS4(String testName) throws Exception {
165 String testDataDir = System.getProperty("test-data.fileName");
167 createFromXmlFile(testName, testDataDir + "/repfield_whitesp4.xml", false);
168 testSubmitRequest(newId);
172 * Tests to diagnose and verify the fixed status of CSPACE-1248,
173 * "Wedged records created!" (i.e. records with child repeatable
174 * fields, which contain null values, can be successfully created
175 * but an error occurs on trying to retrieve those records).
177 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
178 dependsOnMethods = {"create", "testSubmitRequest"})
179 public void createWithNullValueRepeatableField(String testName) throws Exception {
180 String testDataDir = System.getProperty("test-data.fileName");
182 createFromXmlFile(testName, testDataDir + "/repfield_null1.xml", false);
183 if (logger.isDebugEnabled()) {
184 logger.debug("Successfully created record with null value repeatable field.");
185 logger.debug("Attempting to retrieve just-created record ...");
187 testSubmitRequest(newId);
191 * @see org.collectionspace.services.client.test.ServiceTest#createList()
194 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
195 dependsOnMethods = {"create"})
196 public void createList(String testName) throws Exception {
197 for (int i = 0; i < 3; i++) {
203 // Placeholders until the three tests below can be uncommented.
204 // See Issue CSPACE-401.
206 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
207 public void createWithEmptyEntityBody(String testName) throws Exception {
211 * Test how the service handles XML that is not well formed,
212 * when sent in the payload of a Create request.
214 * @param testName The name of this test method. This name is supplied
215 * automatically, via reflection, by a TestNG 'data provider' in
219 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
220 public void createWithMalformedXml(String testName) throws Exception {
221 setupCreate(testName);
225 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
226 public void createWithWrongXmlSchema(String testName) throws Exception {
232 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
233 dependsOnMethods = {"create", "testSubmitRequest"})
234 public void createWithEmptyEntityBody(String testName) throwsException {
237 setupCreateWithEmptyEntityBody(testName);
239 // Submit the request to the service and store the response.
240 String method = REQUEST_TYPE.httpMethodName();
241 String url = getServiceRootURL();
242 String mediaType = MediaType.APPLICATION_XML;
243 final String entity = "";
244 int statusCode = submitRequest(method, url, mediaType, entity);
246 // Check the status code of the response: does it match
247 // the expected response(s)?
248 if(logger.isDebugEnabled()){
249 logger.debug(testName + ": url=" + url +
250 " status=" + statusCode);
252 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
253 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
254 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
258 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
259 dependsOnMethods = {"create", "testSubmitRequest"})
260 public void createWithMalformedXml(String testName) throws Exception {
263 setupCreateWithMalformedXml(testName);
265 // Submit the request to the service and store the response.
266 String method = REQUEST_TYPE.httpMethodName();
267 String url = getServiceRootURL();
268 String mediaType = MediaType.APPLICATION_XML;
269 final String entity = MALFORMED_XML_DATA; // Constant from base class.
270 int statusCode = submitRequest(method, url, mediaType, entity);
272 // Check the status code of the response: does it match
273 // the expected response(s)?
274 if(logger.isDebugEnabled()){
275 logger.debug(testName + ": url=" + url +
276 " status=" + statusCode);
278 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
279 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
280 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
284 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
285 dependsOnMethods = {"create", "testSubmitRequest"})
286 public void createWithWrongXmlSchema(String testName) throws Exception {
289 setupCreateWithWrongXmlSchema(testName);
291 // Submit the request to the service and store the response.
292 String method = REQUEST_TYPE.httpMethodName();
293 String url = getServiceRootURL();
294 String mediaType = MediaType.APPLICATION_XML;
295 final String entity = WRONG_XML_SCHEMA_DATA;
296 int statusCode = submitRequest(method, url, mediaType, entity);
298 // Check the status code of the response: does it match
299 // the expected response(s)?
300 if(logger.isDebugEnabled()){
301 logger.debug(testName + ": url=" + url +
302 " status=" + statusCode);
304 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
305 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
306 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
311 * Test how the service handles, in a Create request, payloads
312 * containing null values (or, in the case of String fields,
313 * empty String values) in one or more fields which must be
314 * present and are required to contain non-empty values.
316 * This is a test of code and/or configuration in the service's
317 * validation routine(s).
319 * @param testName The name of this test method. This name is supplied
320 * automatically, via reflection, by a TestNG 'data provider' in
323 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
324 public void createWithRequiredValuesNullOrEmpty(String testName) throws Exception {
325 setupCreate(testName);
327 // Build a payload with invalid content, by omitting a
328 // field (objectNumber) which must be present, and in which
329 // a non-empty value is required, as enforced by the service's
330 // validation routine(s).
331 CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
332 collectionObject.setTitle("atitle");
333 collectionObject.setObjectName("some name");
335 // Submit the request to the service and store the response.
336 CollectionObjectClient client = new CollectionObjectClient();
337 MultipartOutput multipart =
338 createCollectionObjectInstance(client.getCommonPartName(), collectionObject, null);
339 ClientResponse<Response> res = client.create(multipart);
340 int statusCode = res.getStatus();
342 // Read the response and verify that the create attempt failed.
343 if (logger.isDebugEnabled()) {
344 logger.debug(testName + ": status = " + statusCode);
346 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
347 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
348 Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
350 // FIXME: Consider splitting off the following into its own test method.
352 // Build a payload with invalid content, by setting a value to the
353 // empty String, in a field that requires a non-empty value,
354 // as enforced by the service's validation routine(s).
355 collectionObject = new CollectionobjectsCommon();
356 collectionObject.setTitle("atitle");
357 collectionObject.setObjectName("some name");
358 collectionObject.setObjectNumber("");
360 // Submit the request to the service and store the response.
362 createCollectionObjectInstance(client.getCommonPartName(), collectionObject, null);
363 res = client.create(multipart);
364 statusCode = res.getStatus();
366 // Read the response and verify that the create attempt failed.
367 if (logger.isDebugEnabled()) {
368 logger.debug(testName + ": status = " + statusCode);
370 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
371 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
372 Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
377 // ---------------------------------------------------------------
378 // CRUD tests : READ tests
379 // ---------------------------------------------------------------
382 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
383 dependsOnMethods = {"create"})
384 public void read(String testName) throws Exception {
389 // Submit the request to the service and store the response.
390 CollectionObjectClient client = new CollectionObjectClient();
391 ClientResponse<MultipartInput> res = client.read(knownResourceId);
392 int statusCode = res.getStatus();
394 // Check the status code of the response: does it match
395 // the expected response(s)?
396 if (logger.isDebugEnabled()) {
397 logger.debug(testName + ": status = " + statusCode);
399 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
400 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
401 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
403 MultipartInput input = (MultipartInput) res.getEntity();
405 if (logger.isDebugEnabled()) {
406 logger.debug(testName + ": Reading Common part ...");
408 CollectionobjectsCommon collectionObject =
409 (CollectionobjectsCommon) extractPart(input,
410 client.getCommonPartName(), CollectionobjectsCommon.class);
411 Assert.assertNotNull(collectionObject);
413 if (logger.isDebugEnabled()) {
414 logger.debug(testName + ": Reading Natural History part ...");
416 CollectionobjectsNaturalhistory conh =
417 (CollectionobjectsNaturalhistory) extractPart(input,
418 getNHPartName(), CollectionobjectsNaturalhistory.class);
419 Assert.assertNotNull(conh);
424 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
425 dependsOnMethods = {"read"})
426 public void readNonExistent(String testName) throws Exception {
429 setupReadNonExistent(testName);
431 // Submit the request to the service and store the response.
432 CollectionObjectClient client = new CollectionObjectClient();
433 ClientResponse<MultipartInput> res = client.read(NON_EXISTENT_ID);
434 int statusCode = res.getStatus();
436 // Check the status code of the response: does it match
437 // the expected response(s)?
438 if (logger.isDebugEnabled()) {
439 logger.debug(testName + ": status = " + statusCode);
441 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
442 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
443 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
446 // ---------------------------------------------------------------
447 // CRUD tests : READ_LIST tests
448 // ---------------------------------------------------------------
451 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
452 dependsOnMethods = {"createList", "read"})
453 public void readList(String testName) throws Exception {
456 setupReadList(testName);
458 // Submit the request to the service and store the response.
459 CollectionObjectClient client = new CollectionObjectClient();
460 ClientResponse<CollectionobjectsCommonList> res = client.readList();
461 CollectionobjectsCommonList list = res.getEntity();
462 int statusCode = res.getStatus();
464 // Check the status code of the response: does it match
465 // the expected response(s)?
466 if (logger.isDebugEnabled()) {
467 logger.debug(testName + ": status = " + statusCode);
469 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
470 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
471 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
473 // Optionally output additional data about list members for debugging.
474 boolean iterateThroughList = false;
475 if (iterateThroughList && logger.isDebugEnabled()) {
476 List<CollectionobjectsCommonList.CollectionObjectListItem> items =
477 list.getCollectionObjectListItem();
480 for (CollectionobjectsCommonList.CollectionObjectListItem item : items) {
481 logger.debug(testName + ": list-item[" + i + "] csid="
483 logger.debug(testName + ": list-item[" + i + "] objectNumber="
484 + item.getObjectNumber());
485 logger.debug(testName + ": list-item[" + i + "] URI="
495 // ---------------------------------------------------------------
496 // CRUD tests : UPDATE tests
497 // ---------------------------------------------------------------
500 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
501 dependsOnMethods = {"read"})
502 public void update(String testName) throws Exception {
505 setupUpdate(testName);
507 // Read an existing resource that will be updated.
508 ClientResponse<MultipartInput> res = updateRetrieve(testName, knownResourceId);
510 // Extract its common part.
511 CollectionObjectClient client = new CollectionObjectClient();
512 MultipartInput input = (MultipartInput) res.getEntity();
513 CollectionobjectsCommon collectionObject =
514 (CollectionobjectsCommon) extractPart(input,
515 client.getCommonPartName(), CollectionobjectsCommon.class);
516 Assert.assertNotNull(collectionObject);
518 // Change the content of one or more fields in the common part.
519 collectionObject.setObjectNumber("updated-" + collectionObject.getObjectNumber());
520 collectionObject.setObjectName("updated-" + collectionObject.getObjectName());
521 if (logger.isDebugEnabled()) {
522 logger.debug("sparse update that will be sent in update request:");
523 logger.debug(objectAsXmlString(collectionObject,
524 CollectionobjectsCommon.class));
527 // Send the changed resource to be updated.
528 res = updateSend(testName, knownResourceId, collectionObject);
529 int statusCode = res.getStatus();
530 // Check the status code of the response: does it match the expected response(s)?
531 if (logger.isDebugEnabled()) {
532 logger.debug(testName + ": status = " + statusCode);
534 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
535 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
536 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
538 // Read the response and verify that the resource was correctly updated.
539 input = (MultipartInput) res.getEntity();
540 CollectionobjectsCommon updatedCollectionObject =
541 (CollectionobjectsCommon) extractPart(input,
542 client.getCommonPartName(), CollectionobjectsCommon.class);
543 Assert.assertNotNull(updatedCollectionObject);
544 Assert.assertEquals(updatedCollectionObject.getObjectName(),
545 collectionObject.getObjectName(),
546 "Data in updated object did not match submitted data.");
550 private ClientResponse<MultipartInput> updateRetrieve(String testName, String id) {
551 final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
552 CollectionObjectClient client = new CollectionObjectClient();
553 ClientResponse<MultipartInput> res = client.read(id);
554 if (logger.isDebugEnabled()) {
555 logger.debug("read in updateRetrieve for " + testName + " status = " + res.getStatus());
557 Assert.assertEquals(res.getStatus(), EXPECTED_STATUS);
558 if (logger.isDebugEnabled()) {
559 logger.debug("got object to updateRetrieve for " + testName + " with ID: " + id);
564 private ClientResponse<MultipartInput> updateSend(String testName, String id,
565 CollectionobjectsCommon collectionObject) {
566 MultipartOutput output = new MultipartOutput();
567 OutputPart commonPart = output.addPart(collectionObject, MediaType.APPLICATION_XML_TYPE);
568 CollectionObjectClient client = new CollectionObjectClient();
569 commonPart.getHeaders().add("label", client.getCommonPartName());
570 ClientResponse<MultipartInput> res = client.update(knownResourceId, output);
575 // Placeholders until the three tests below can be uncommented.
576 // See Issue CSPACE-401.
578 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
579 dependsOnMethods = {"read"})
580 public void updateWithEmptyEntityBody(String testName) throws Exception {
584 * Test how the service handles XML that is not well formed,
585 * when sent in the payload of an Update request.
587 * @param testName The name of this test method. This name is supplied
588 * automatically, via reflection, by a TestNG 'data provider' in
592 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
593 dependsOnMethods = {"read"})
594 public void updateWithMalformedXml(String testName) throws Exception {
598 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
599 dependsOnMethods = {"read"})
600 public void updateWithWrongXmlSchema(String testName) throws Exception {
605 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
606 dependsOnMethods = {"create", "update", "testSubmitRequest"})
607 public void updateWithEmptyEntityBody(String testName) throws Exception {
610 setupUpdateWithEmptyEntityBody(testName);
612 // Submit the request to the service and store the response.
613 String method = REQUEST_TYPE.httpMethodName();
614 String url = getResourceURL(knownResourceId);
615 String mediaType = MediaType.APPLICATION_XML;
616 final String entity = "";
617 int statusCode = submitRequest(method, url, mediaType, entity);
619 // Check the status code of the response: does it match
620 // the expected response(s)?
621 if(logger.isDebugEnabled()){
622 logger.debug(testName + ": url=" + url +
623 " status=" + statusCode);
625 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
626 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
627 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
631 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
632 dependsOnMethods = {"create", "update", "testSubmitRequest"})
633 public void updateWithMalformedXml() throws Exception {
636 setupUpdateWithMalformedXml(testName);
638 // Submit the request to the service and store the response.
639 String method = REQUEST_TYPE.httpMethodName();
640 String url = getResourceURL(knownResourceId);
641 final String entity = MALFORMED_XML_DATA;
642 String mediaType = MediaType.APPLICATION_XML;
643 int statusCode = submitRequest(method, url, mediaType, entity);
645 // Check the status code of the response: does it match
646 // the expected response(s)?
647 if(logger.isDebugEnabled()){
648 logger.debug(testName + ": url=" + url +
649 " status=" + statusCode);
651 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
652 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
653 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
657 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
658 dependsOnMethods = {"create", "update", "testSubmitRequest"})
659 public void updateWithWrongXmlSchema(String testName) throws Exception {
662 setupUpdateWithWrongXmlSchema(String testName);
664 // Submit the request to the service and store the response.
665 String method = REQUEST_TYPE.httpMethodName();
666 String url = getResourceURL(knownResourceId);
667 String mediaType = MediaType.APPLICATION_XML;
668 final String entity = WRONG_XML_SCHEMA_DATA;
669 int statusCode = submitRequest(method, url, mediaType, entity);
671 // Check the status code of the response: does it match
672 // the expected response(s)?
673 if(logger.isDebugEnabled()){
674 logger.debug(testName + ": url=" + url +
675 " status=" + statusCode);
677 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
678 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
679 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
684 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
685 dependsOnMethods = {"update", "testSubmitRequest"})
686 public void updateNonExistent(String testName) throws Exception {
689 setupUpdateNonExistent(testName);
691 // Submit the request to the service and store the response.
693 // Note: The ID used in this 'create' call may be arbitrary.
694 // The only relevant ID may be the one used in updateCollectionObject(), below.
695 CollectionObjectClient client = new CollectionObjectClient();
696 MultipartOutput multipart =
697 createCollectionObjectInstance(client.getCommonPartName(),
699 ClientResponse<MultipartInput> res =
700 client.update(NON_EXISTENT_ID, multipart);
701 int statusCode = res.getStatus();
703 // Check the status code of the response: does it match
704 // the expected response(s)?
705 if (logger.isDebugEnabled()) {
706 logger.debug(testName + ": status = " + statusCode);
708 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
709 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
710 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
714 * Test how the service handles, in an Update request, payloads
715 * containing null values (or, in the case of String fields,
716 * empty String values) in one or more fields in which non-empty
717 * values are required.
719 * This is a test of code and/or configuration in the service's
720 * validation routine(s).
722 * @param testName The name of this test method. This name is supplied
723 * automatically, via reflection, by a TestNG 'data provider' in
726 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
727 dependsOnMethods = {"read"})
728 public void updateWithRequiredValuesNullOrEmpty(String testName) throws Exception {
730 setupUpdate(testName);
731 if (logger.isDebugEnabled()) {
732 logger.debug(testName + " got object to update with ID: " + knownResourceId);
735 // Read an existing record for updating.
736 ClientResponse<MultipartInput> res = updateRetrieve(testName, knownResourceId);
738 CollectionObjectClient client = new CollectionObjectClient();
739 MultipartInput input = (MultipartInput) res.getEntity();
740 CollectionobjectsCommon collectionObject =
741 (CollectionobjectsCommon) extractPart(input,
742 client.getCommonPartName(), CollectionobjectsCommon.class);
743 Assert.assertNotNull(collectionObject);
745 // Update with invalid content, by setting a value to the
746 // empty String, in a field that requires a non-empty value,
747 // as enforced by the service's validation routine(s).
748 collectionObject.setObjectNumber("");
750 if (logger.isDebugEnabled()) {
751 logger.debug(testName + " updated object");
752 logger.debug(objectAsXmlString(collectionObject,
753 CollectionobjectsCommon.class));
756 // Submit the request to the service and store the response.
757 res = updateSend(testName, knownResourceId, collectionObject);
758 int statusCode = res.getStatus();
760 // Read the response and verify that the update attempt failed.
761 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
762 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
763 Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
767 // ---------------------------------------------------------------
768 // CRUD tests : DELETE tests
769 // ---------------------------------------------------------------
772 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
773 dependsOnMethods = {"create", "readList", "testSubmitRequest", "update"})
774 public void delete(String testName) throws Exception {
777 setupDelete(testName);
779 // Submit the request to the service and store the response.
780 CollectionObjectClient client = new CollectionObjectClient();
781 ClientResponse<Response> res = client.delete(knownResourceId);
782 int statusCode = res.getStatus();
784 // Check the status code of the response: does it match
785 // the expected response(s)?
786 if (logger.isDebugEnabled()) {
787 logger.debug(testName + ": status = " + statusCode);
789 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
790 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
791 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
796 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
797 dependsOnMethods = {"delete"})
798 public void deleteNonExistent(String testName) throws Exception {
801 setupDeleteNonExistent(testName);
803 // Submit the request to the service and store the response.
804 CollectionObjectClient client = new CollectionObjectClient();
805 ClientResponse<Response> res = client.delete(NON_EXISTENT_ID);
806 int statusCode = res.getStatus();
808 // Check the status code of the response: does it match
809 // the expected response(s)?
810 if (logger.isDebugEnabled()) {
811 logger.debug(testName + ": status = " + statusCode);
813 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
814 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
815 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
818 // ---------------------------------------------------------------
819 // Utility tests : tests of code used in tests above
820 // ---------------------------------------------------------------
822 * Tests the code for manually submitting data that is used by several
823 * of the methods above.
826 @Test(dependsOnMethods = {"create", "read"})
827 public void testSubmitRequest() throws Exception {
828 testSubmitRequest(knownResourceId);
831 private void testSubmitRequest(String resourceId) throws Exception {
833 // Expected status code: 200 OK
834 final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
836 // Submit the request to the service and store the response.
837 String method = ServiceRequestType.READ.httpMethodName();
838 String url = getResourceURL(resourceId);
839 int statusCode = submitRequest(method, url);
841 // Check the status code of the response: does it match
842 // the expected response(s)?
843 if (logger.isDebugEnabled()) {
844 logger.debug("testSubmitRequest: url=" + url
845 + " status=" + statusCode);
847 Assert.assertEquals(statusCode, EXPECTED_STATUS);
851 // ---------------------------------------------------------------
852 // Cleanup of resources created during testing
853 // ---------------------------------------------------------------
855 * Deletes all resources created by tests, after all tests have been run.
857 * This cleanup method will always be run, even if one or more tests fail.
858 * For this reason, it attempts to remove all resources created
859 * at any point during testing, even if some of those resources
860 * may be expected to be deleted by certain tests.
862 @AfterClass(alwaysRun = true)
863 public void cleanUp() {
864 if (logger.isDebugEnabled()) {
865 logger.debug("Cleaning up temporary resources created for testing ...");
867 CollectionObjectClient client = new CollectionObjectClient();
868 for (String resourceId : allResourceIdsCreated) {
869 // Note: Any non-success responses are ignored and not reported.
870 ClientResponse<Response> res = client.delete(resourceId);
874 // ---------------------------------------------------------------
875 // Utility methods used by tests above
876 // ---------------------------------------------------------------
877 private MultipartOutput createCollectionObjectInstance(String commonPartName,
879 return createCollectionObjectInstance(commonPartName,
880 "objectNumber-" + identifier,
881 "objectName-" + identifier);
884 private MultipartOutput createCollectionObjectInstance(String commonPartName,
885 String objectNumber, String objectName) {
886 CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
887 ResponsibleDepartmentList deptList = new ResponsibleDepartmentList();
888 List<String> depts = deptList.getResponsibleDepartment();
889 // @TODO Use properly formatted refNames for representative departments
890 // in this example test record. The following are mere placeholders.
891 depts.add("urn:org.collectionspace.services.department:Registrar");
893 depts.add("urn:org.walkerart.department:Fine Art");
895 multivalue = !multivalue;
896 //FIXME: Title does not need to be set.
897 collectionObject.setTitle("atitle");
898 collectionObject.setResponsibleDepartments(deptList);
899 collectionObject.setObjectNumber(objectNumber);
900 collectionObject.setOtherNumber("urn:org.walkerart.id:123");
901 collectionObject.setObjectName(objectName);
902 collectionObject.setAge(""); //test for null string
903 collectionObject.setBriefDescription("Papier mache bird cow mask with horns, "
904 + "painted red with black and yellow spots. "
905 + "Puerto Rico. ca. 8" high, 6" wide, projects 10" (with horns).");
907 CollectionobjectsNaturalhistory conh = new CollectionobjectsNaturalhistory();
908 conh.setNhString("test-string");
910 conh.setNhLong(9999);
913 MultipartOutput multipart = createCollectionObjectInstance(commonPartName, collectionObject, conh);
917 private MultipartOutput createCollectionObjectInstance(String commonPartName,
918 CollectionobjectsCommon collectionObject, CollectionobjectsNaturalhistory conh) {
920 MultipartOutput multipart = new MultipartOutput();
921 OutputPart commonPart = multipart.addPart(collectionObject,
922 MediaType.APPLICATION_XML_TYPE);
923 commonPart.getHeaders().add("label", commonPartName);
925 if (logger.isDebugEnabled()) {
926 logger.debug("to be created, collectionobject common");
927 logger.debug(objectAsXmlString(collectionObject,
928 CollectionobjectsCommon.class));
932 OutputPart nhPart = multipart.addPart(conh, MediaType.APPLICATION_XML_TYPE);
933 nhPart.getHeaders().add("label", getNHPartName());
935 if (logger.isDebugEnabled()) {
936 logger.debug("to be created, collectionobject nhistory");
937 logger.debug(objectAsXmlString(conh,
938 CollectionobjectsNaturalhistory.class));
946 * createCollectionObjectInstanceFromXml uses JAXB unmarshaller to retrieve
947 * collectionobject from given file
948 * @param commonPartName
949 * @param commonPartFileName
953 private MultipartOutput createCollectionObjectInstanceFromXml(String testName, String commonPartName,
954 String commonPartFileName) throws Exception {
956 CollectionobjectsCommon collectionObject =
957 (CollectionobjectsCommon) getObjectFromFile(CollectionobjectsCommon.class,
959 MultipartOutput multipart = new MultipartOutput();
960 OutputPart commonPart = multipart.addPart(collectionObject,
961 MediaType.APPLICATION_XML_TYPE);
962 commonPart.getHeaders().add("label", commonPartName);
964 if (logger.isDebugEnabled()) {
965 logger.debug(testName + " to be created, collectionobject common");
966 logger.debug(objectAsXmlString(collectionObject,
967 CollectionobjectsCommon.class));
974 * createCollectionObjectInstanceFromRawXml uses stringified collectionobject
975 * retrieve from given file
976 * @param commonPartName
977 * @param commonPartFileName
981 private MultipartOutput createCollectionObjectInstanceFromRawXml(String testName, String commonPartName,
982 String commonPartFileName) throws Exception {
984 MultipartOutput multipart = new MultipartOutput();
985 String stringObject = getXmlDocumentAsString(commonPartFileName);
986 if (logger.isDebugEnabled()) {
987 logger.debug(testName + " to be created, collectionobject common " + "\n" + stringObject);
989 OutputPart commonPart = multipart.addPart(stringObject,
990 MediaType.APPLICATION_XML_TYPE);
991 commonPart.getHeaders().add("label", commonPartName);
997 private String getNHPartName() {
998 return "collectionobjects_naturalhistory";
1001 private String createFromXmlFile(String testName, String fileName, boolean useJaxb) throws Exception {
1002 // Perform setup, such as initializing the type of service request
1003 // (e.g. CREATE, DELETE), its valid and expected status codes, and
1004 // its associated HTTP method name (e.g. POST, DELETE).
1005 setupCreate(testName);
1007 MultipartOutput multipart = null;
1009 CollectionObjectClient client = new CollectionObjectClient();
1011 multipart = createCollectionObjectInstanceFromXml(testName,
1012 client.getCommonPartName(), fileName);
1014 multipart = createCollectionObjectInstanceFromRawXml(testName,
1015 client.getCommonPartName(), fileName);
1017 ClientResponse<Response> res = client.create(multipart);
1018 int statusCode = res.getStatus();
1020 if (logger.isDebugEnabled()) {
1021 logger.debug(testName + ": status = " + statusCode);
1023 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
1024 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
1025 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
1026 String newId = extractId(res);
1027 allResourceIdsCreated.add(newId);