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.List;
26 import javax.ws.rs.core.MediaType;
27 import javax.ws.rs.core.Response;
29 //import org.collectionspace.services.client.AbstractServiceClientImpl;
30 import org.collectionspace.services.client.CollectionObjectClient;
31 import org.collectionspace.services.client.CollectionObjectFactory;
32 import org.collectionspace.services.client.CollectionSpaceClient;
33 import org.collectionspace.services.collectionobject.CollectionobjectsCommon;
34 import org.collectionspace.services.collectionobject.domain.naturalhistory.CollectionobjectsNaturalhistory;
35 import org.collectionspace.services.collectionobject.CollectionobjectsCommonList;
36 import org.collectionspace.services.collectionobject.ResponsibleDepartmentList;
37 import org.collectionspace.services.collectionobject.OtherNumber;
38 import org.collectionspace.services.collectionobject.OtherNumberList;
40 import org.collectionspace.services.jaxb.AbstractCommonList;
42 import org.jboss.resteasy.client.ClientResponse;
43 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
44 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
45 import org.jboss.resteasy.plugins.providers.multipart.OutputPart;
46 import org.testng.Assert;
47 import org.testng.annotations.Test;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
53 * CollectionObjectServiceTest, carries out tests against a
54 * deployed and running CollectionObject Service.
56 * $LastChangedRevision$
59 public class CollectionObjectServiceTest extends AbstractServiceTestImpl {
62 private final Logger logger =
63 LoggerFactory.getLogger(CollectionObjectServiceTest.class);
64 // Instance variables specific to this test.
65 /** The known resource id. */
66 private String knownResourceId = null;
68 /** The multivalue. */
69 private boolean multivalue; //toggle
72 * @see org.collectionspace.services.client.test.BaseServiceTest#getServicePathComponent()
75 protected String getServicePathComponent() {
76 return new CollectionObjectClient().getServicePathComponent();
80 * @see org.collectionspace.services.client.test.BaseServiceTest#getClientInstance()
83 protected CollectionSpaceClient getClientInstance() {
84 return new CollectionObjectClient();
88 * @see org.collectionspace.services.client.test.BaseServiceTest#getAbstractCommonList(org.jboss.resteasy.client.ClientResponse)
91 protected AbstractCommonList getAbstractCommonList(
92 ClientResponse<AbstractCommonList> response) {
93 return response.getEntity(CollectionobjectsCommonList.class);
96 // ---------------------------------------------------------------
97 // CRUD tests : CREATE tests
98 // ---------------------------------------------------------------
101 * @see org.collectionspace.services.client.test.ServiceTest#create(java.lang.String)
104 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
105 public void create(String testName) throws Exception {
107 // Perform setup, such as initializing the type of service request
108 // (e.g. CREATE, DELETE), its valid and expected status codes, and
109 // its associated HTTP method name (e.g. POST, DELETE).
110 setupCreate(testName);
112 // Submit the request to the service and store the response.
113 CollectionObjectClient client = new CollectionObjectClient();
114 String identifier = createIdentifier();
115 MultipartOutput multipart =
116 createCollectionObjectInstance(client.getCommonPartName(), identifier);
117 ClientResponse<Response> res = client.create(multipart);
118 int statusCode = res.getStatus();
120 // Check the status code of the response: does it match
121 // the expected response(s)?
124 // Does it fall within the set of valid status codes?
125 // Does it exactly match the expected status code?
126 if (logger.isDebugEnabled()) {
127 logger.debug(testName + ": status = " + statusCode);
129 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
130 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
131 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
133 // Store the ID returned from the first resource created
134 // for additional tests below.
135 if (knownResourceId == null) {
136 knownResourceId = extractId(res);
137 if (logger.isDebugEnabled()) {
138 logger.debug(testName + ": knownResourceId=" + knownResourceId);
142 // Store the IDs from every resource created by tests,
143 // so they can be deleted after tests have been run.
144 allResourceIdsCreated.add(extractId(res));
149 * Tests to diagnose and verify the fixed status of CSPACE-1026,
150 * "Whitespace at certain points in payload cause failure"
153 * Creates the from xml cambridge.
155 * @param testName the test name
156 * @throws Exception the exception
158 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
159 dependsOnMethods = {"create", "testSubmitRequest"})
160 public void createFromXmlCambridge(String testName) throws Exception {
162 createFromXmlFile(testName, "./test-data/testCambridge.xml", true);
163 testSubmitRequest(newId);
167 * Creates the from xml rfw s1.
169 * @param testName the test name
170 * @throws Exception the exception
172 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
173 dependsOnMethods = {"create", "testSubmitRequest"})
174 public void createFromXmlRFWS1(String testName) throws Exception {
175 String testDataDir = System.getProperty("test-data.fileName");
177 //createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp1.xml", false);
178 createFromXmlFile(testName, testDataDir + "/repfield_whitesp1.xml", false);
179 testSubmitRequest(newId);
183 * Creates the from xml rfw s2.
185 * @param testName the test name
186 * @throws Exception the exception
188 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
189 dependsOnMethods = {"create", "testSubmitRequest"})
190 public void createFromXmlRFWS2(String testName) throws Exception {
191 String testDataDir = System.getProperty("test-data.fileName");
193 //createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp2.xml", false);
194 createFromXmlFile(testName, testDataDir + "/repfield_whitesp2.xml", false);
195 testSubmitRequest(newId);
199 * Creates the from xml rfw s3.
201 * @param testName the test name
202 * @throws Exception the exception
204 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
205 dependsOnMethods = {"create", "testSubmitRequest"})
206 public void createFromXmlRFWS3(String testName) throws Exception {
207 String testDataDir = System.getProperty("test-data.fileName");
209 //createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp3.xml", false);
210 createFromXmlFile(testName, testDataDir + "/repfield_whitesp3.xml", false);
211 testSubmitRequest(newId);
215 * Creates the from xml rfw s4.
217 * @param testName the test name
218 * @throws Exception the exception
220 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
221 dependsOnMethods = {"create", "testSubmitRequest"})
222 public void createFromXmlRFWS4(String testName) throws Exception {
223 String testDataDir = System.getProperty("test-data.fileName");
225 createFromXmlFile(testName, testDataDir + "/repfield_whitesp4.xml", false);
226 testSubmitRequest(newId);
230 * Tests to diagnose and verify the fixed status of CSPACE-1248,
231 * "Wedged records created!" (i.e. records with child repeatable
232 * fields, which contain null values, can be successfully created
233 * but an error occurs on trying to retrieve those records).
236 * Creates the with null value repeatable field.
238 * @param testName the test name
239 * @throws Exception the exception
241 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
242 dependsOnMethods = {"create", "testSubmitRequest"})
243 public void createWithNullValueRepeatableField(String testName) throws Exception {
244 String testDataDir = System.getProperty("test-data.fileName");
246 createFromXmlFile(testName, testDataDir + "/repfield_null1.xml", false);
247 if (logger.isDebugEnabled()) {
248 logger.debug("Successfully created record with null value repeatable field.");
249 logger.debug("Attempting to retrieve just-created record ...");
251 testSubmitRequest(newId);
255 * @see org.collectionspace.services.client.test.ServiceTest#createList()
258 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
259 dependsOnMethods = {"create"})
260 public void createList(String testName) throws Exception {
261 this.createPaginatedList(testName, DEFAULT_LIST_SIZE);
265 // Placeholders until the three tests below can be uncommented.
266 // See Issue CSPACE-401.
268 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#createWithEmptyEntityBody(java.lang.String)
271 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
272 public void createWithEmptyEntityBody(String testName) throws Exception {
273 //FIXME: Should this test really be empty?
277 * Test how the service handles XML that is not well formed,
278 * when sent in the payload of a Create request.
280 * @param testName The name of this test method. This name is supplied
281 * automatically, via reflection, by a TestNG 'data provider' in
285 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
286 public void createWithMalformedXml(String testName) throws Exception {
287 setupCreate(testName);
291 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#createWithWrongXmlSchema(java.lang.String)
294 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
295 public void createWithWrongXmlSchema(String testName) throws Exception {
296 //FIXME: Should this test really be empty?
302 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
303 dependsOnMethods = {"create", "testSubmitRequest"})
304 public void createWithEmptyEntityBody(String testName) throwsException {
307 setupCreateWithEmptyEntityBody(testName);
309 // Submit the request to the service and store the response.
310 String method = REQUEST_TYPE.httpMethodName();
311 String url = getServiceRootURL();
312 String mediaType = MediaType.APPLICATION_XML;
313 final String entity = "";
314 int statusCode = submitRequest(method, url, mediaType, entity);
316 // Check the status code of the response: does it match
317 // the expected response(s)?
318 if(logger.isDebugEnabled()){
319 logger.debug(testName + ": url=" + url +
320 " status=" + statusCode);
322 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
323 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
324 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
328 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
329 dependsOnMethods = {"create", "testSubmitRequest"})
330 public void createWithMalformedXml(String testName) throws Exception {
333 setupCreateWithMalformedXml(testName);
335 // Submit the request to the service and store the response.
336 String method = REQUEST_TYPE.httpMethodName();
337 String url = getServiceRootURL();
338 String mediaType = MediaType.APPLICATION_XML;
339 final String entity = MALFORMED_XML_DATA; // Constant from base class.
340 int statusCode = submitRequest(method, url, mediaType, entity);
342 // Check the status code of the response: does it match
343 // the expected response(s)?
344 if(logger.isDebugEnabled()){
345 logger.debug(testName + ": url=" + url +
346 " status=" + statusCode);
348 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
349 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
350 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
354 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
355 dependsOnMethods = {"create", "testSubmitRequest"})
356 public void createWithWrongXmlSchema(String testName) throws Exception {
359 setupCreateWithWrongXmlSchema(testName);
361 // Submit the request to the service and store the response.
362 String method = REQUEST_TYPE.httpMethodName();
363 String url = getServiceRootURL();
364 String mediaType = MediaType.APPLICATION_XML;
365 final String entity = WRONG_XML_SCHEMA_DATA;
366 int statusCode = submitRequest(method, url, mediaType, entity);
368 // Check the status code of the response: does it match
369 // the expected response(s)?
370 if(logger.isDebugEnabled()){
371 logger.debug(testName + ": url=" + url +
372 " status=" + statusCode);
374 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
375 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
376 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
381 * Test how the service handles, in a Create request, payloads
382 * containing null values (or, in the case of String fields,
383 * empty String values) in one or more fields which must be
384 * present and are required to contain non-empty values.
386 * This is a test of code and/or configuration in the service's
387 * validation routine(s).
389 * @param testName The name of this test method. This name is supplied
390 * automatically, via reflection, by a TestNG 'data provider' in
394 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
395 public void createWithRequiredValuesNullOrEmpty(String testName) throws Exception {
396 setupCreate(testName);
398 // Build a payload with invalid content, by omitting a
399 // field (objectNumber) which must be present, and in which
400 // a non-empty value is required, as enforced by the service's
401 // validation routine(s).
402 CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
403 collectionObject.setTitle("atitle");
404 collectionObject.setObjectName("some name");
406 // Submit the request to the service and store the response.
407 CollectionObjectClient client = new CollectionObjectClient();
408 MultipartOutput multipart =
409 createCollectionObjectInstance(client.getCommonPartName(), collectionObject, null);
410 ClientResponse<Response> res = client.create(multipart);
411 int statusCode = res.getStatus();
413 // Read the response and verify that the create attempt failed.
414 if (logger.isDebugEnabled()) {
415 logger.debug(testName + ": status = " + statusCode);
417 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
418 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
419 Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
421 // FIXME: Consider splitting off the following into its own test method.
423 // Build a payload with invalid content, by setting a value to the
424 // empty String, in a field that requires a non-empty value,
425 // as enforced by the service's validation routine(s).
426 collectionObject = new CollectionobjectsCommon();
427 collectionObject.setTitle("atitle");
428 collectionObject.setObjectName("some name");
429 collectionObject.setObjectNumber("");
431 // Submit the request to the service and store the response.
433 createCollectionObjectInstance(client.getCommonPartName(), collectionObject, null);
434 res = client.create(multipart);
435 statusCode = res.getStatus();
437 // Read the response and verify that the create attempt failed.
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, Response.Status.BAD_REQUEST.getStatusCode());
448 // ---------------------------------------------------------------
449 // CRUD tests : READ tests
450 // ---------------------------------------------------------------
453 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#read(java.lang.String)
456 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
457 dependsOnMethods = {"create"})
458 public void read(String testName) throws Exception {
463 // Submit the request to the service and store the response.
464 CollectionObjectClient client = new CollectionObjectClient();
465 ClientResponse<MultipartInput> res = client.read(knownResourceId);
466 int statusCode = res.getStatus();
468 // Check the status code of the response: does it match
469 // the expected response(s)?
470 if (logger.isDebugEnabled()) {
471 logger.debug(testName + ": status = " + statusCode);
473 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
474 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
475 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
477 MultipartInput input = (MultipartInput) res.getEntity();
479 if (logger.isDebugEnabled()) {
480 logger.debug(testName + ": Reading Common part ...");
482 CollectionobjectsCommon collectionObject =
483 (CollectionobjectsCommon) extractPart(input,
484 client.getCommonPartName(), CollectionobjectsCommon.class);
485 Assert.assertNotNull(collectionObject);
487 if (logger.isDebugEnabled()) {
488 logger.debug(testName + ": Reading Natural History part ...");
490 CollectionobjectsNaturalhistory conh =
491 (CollectionobjectsNaturalhistory) extractPart(input,
492 getNHPartName(), CollectionobjectsNaturalhistory.class);
493 Assert.assertNotNull(conh);
498 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#readNonExistent(java.lang.String)
501 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
502 dependsOnMethods = {"read"})
503 public void readNonExistent(String testName) throws Exception {
506 setupReadNonExistent(testName);
508 // Submit the request to the service and store the response.
509 CollectionObjectClient client = new CollectionObjectClient();
510 ClientResponse<MultipartInput> res = client.read(NON_EXISTENT_ID);
511 int statusCode = res.getStatus();
513 // Check the status code of the response: does it match
514 // the expected response(s)?
515 if (logger.isDebugEnabled()) {
516 logger.debug(testName + ": status = " + statusCode);
518 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
519 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
520 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
524 // ---------------------------------------------------------------
525 // CRUD tests : READ_LIST tests
526 // ---------------------------------------------------------------
529 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#readList(java.lang.String)
532 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
533 dependsOnMethods = {"createList", "read"})
534 public void readList(String testName) throws Exception {
537 setupReadList(testName);
539 // Submit the request to the service and store the response.
540 CollectionObjectClient client = new CollectionObjectClient();
541 ClientResponse<CollectionobjectsCommonList> res = client.readList();
542 CollectionobjectsCommonList list = res.getEntity();
543 int statusCode = res.getStatus();
545 // Check the status code of the response: does it match
546 // the expected response(s)?
547 if (logger.isDebugEnabled()) {
548 logger.debug(testName + ": status = " + statusCode);
550 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
551 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
552 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
554 // Optionally output additional data about list members for debugging.
555 boolean iterateThroughList = false;
556 if (iterateThroughList && logger.isDebugEnabled()) {
557 List<CollectionobjectsCommonList.CollectionObjectListItem> items =
558 list.getCollectionObjectListItem();
561 for (CollectionobjectsCommonList.CollectionObjectListItem item : items) {
562 logger.debug(testName + ": list-item[" + i + "] csid="
564 logger.debug(testName + ": list-item[" + i + "] objectNumber="
565 + item.getObjectNumber());
566 logger.debug(testName + ": list-item[" + i + "] URI="
576 // ---------------------------------------------------------------
577 // CRUD tests : UPDATE tests
578 // ---------------------------------------------------------------
581 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#update(java.lang.String)
584 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
585 dependsOnMethods = {"read"})
586 public void update(String testName) throws Exception {
589 setupUpdate(testName);
591 // Read an existing resource that will be updated.
592 ClientResponse<MultipartInput> res = updateRetrieve(testName, knownResourceId);
594 // Extract its common part.
595 CollectionObjectClient client = new CollectionObjectClient();
596 MultipartInput input = (MultipartInput) res.getEntity();
597 CollectionobjectsCommon collectionObject =
598 (CollectionobjectsCommon) extractPart(input,
599 client.getCommonPartName(), CollectionobjectsCommon.class);
600 Assert.assertNotNull(collectionObject);
602 // Change the content of one or more fields in the common part.
603 collectionObject.setObjectNumber("updated-" + collectionObject.getObjectNumber());
604 collectionObject.setObjectName("updated-" + collectionObject.getObjectName());
605 if (logger.isDebugEnabled()) {
606 logger.debug("sparse update that will be sent in update request:");
607 logger.debug(objectAsXmlString(collectionObject,
608 CollectionobjectsCommon.class));
611 // Send the changed resource to be updated.
612 res = updateSend(testName, knownResourceId, collectionObject);
613 int statusCode = res.getStatus();
614 // Check the status code of the response: does it match the expected response(s)?
615 if (logger.isDebugEnabled()) {
616 logger.debug(testName + ": status = " + statusCode);
618 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
619 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
620 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
622 // Read the response and verify that the resource was correctly updated.
623 input = (MultipartInput) res.getEntity();
624 CollectionobjectsCommon updatedCollectionObject =
625 (CollectionobjectsCommon) extractPart(input,
626 client.getCommonPartName(), CollectionobjectsCommon.class);
627 Assert.assertNotNull(updatedCollectionObject);
628 Assert.assertEquals(updatedCollectionObject.getObjectName(),
629 collectionObject.getObjectName(),
630 "Data in updated object did not match submitted data.");
637 * @param testName the test name
639 * @return the client response
641 private ClientResponse<MultipartInput> updateRetrieve(String testName, String id) {
642 final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
643 CollectionObjectClient client = new CollectionObjectClient();
644 ClientResponse<MultipartInput> res = client.read(id);
645 if (logger.isDebugEnabled()) {
646 logger.debug("read in updateRetrieve for " + testName + " status = " + res.getStatus());
648 Assert.assertEquals(res.getStatus(), EXPECTED_STATUS);
649 if (logger.isDebugEnabled()) {
650 logger.debug("got object to updateRetrieve for " + testName + " with ID: " + id);
658 * @param testName the test name
660 * @param collectionObject the collection object
661 * @return the client response
663 private ClientResponse<MultipartInput> updateSend(String testName, String id,
664 CollectionobjectsCommon collectionObject) {
665 MultipartOutput output = new MultipartOutput();
666 OutputPart commonPart = output.addPart(collectionObject, MediaType.APPLICATION_XML_TYPE);
667 CollectionObjectClient client = new CollectionObjectClient();
668 commonPart.getHeaders().add("label", client.getCommonPartName());
669 ClientResponse<MultipartInput> res = client.update(knownResourceId, output);
674 // Placeholders until the three tests below can be uncommented.
675 // See Issue CSPACE-401.
677 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateWithEmptyEntityBody(java.lang.String)
680 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
681 dependsOnMethods = {"read"})
682 public void updateWithEmptyEntityBody(String testName) throws Exception {
683 //FIXME: Should this test really be empty?
687 * Test how the service handles XML that is not well formed,
688 * when sent in the payload of an Update request.
690 * @param testName The name of this test method. This name is supplied
691 * automatically, via reflection, by a TestNG 'data provider' in
695 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
696 dependsOnMethods = {"read"})
697 public void updateWithMalformedXml(String testName) throws Exception {
698 //FIXME: Should this test really be empty?
702 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateWithWrongXmlSchema(java.lang.String)
705 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
706 dependsOnMethods = {"read"})
707 public void updateWithWrongXmlSchema(String testName) throws Exception {
708 //FIXME: Should this test really be empty?
713 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
714 dependsOnMethods = {"create", "update", "testSubmitRequest"})
715 public void updateWithEmptyEntityBody(String testName) throws Exception {
718 setupUpdateWithEmptyEntityBody(testName);
720 // Submit the request to the service and store the response.
721 String method = REQUEST_TYPE.httpMethodName();
722 String url = getResourceURL(knownResourceId);
723 String mediaType = MediaType.APPLICATION_XML;
724 final String entity = "";
725 int statusCode = submitRequest(method, url, mediaType, entity);
727 // Check the status code of the response: does it match
728 // the expected response(s)?
729 if(logger.isDebugEnabled()){
730 logger.debug(testName + ": url=" + url +
731 " status=" + statusCode);
733 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
734 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
735 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
739 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
740 dependsOnMethods = {"create", "update", "testSubmitRequest"})
741 public void updateWithMalformedXml() throws Exception {
744 setupUpdateWithMalformedXml(testName);
746 // Submit the request to the service and store the response.
747 String method = REQUEST_TYPE.httpMethodName();
748 String url = getResourceURL(knownResourceId);
749 final String entity = MALFORMED_XML_DATA;
750 String mediaType = MediaType.APPLICATION_XML;
751 int statusCode = submitRequest(method, url, mediaType, entity);
753 // Check the status code of the response: does it match
754 // the expected response(s)?
755 if(logger.isDebugEnabled()){
756 logger.debug(testName + ": url=" + url +
757 " status=" + statusCode);
759 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
760 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
761 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
765 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
766 dependsOnMethods = {"create", "update", "testSubmitRequest"})
767 public void updateWithWrongXmlSchema(String testName) throws Exception {
770 setupUpdateWithWrongXmlSchema(String testName);
772 // Submit the request to the service and store the response.
773 String method = REQUEST_TYPE.httpMethodName();
774 String url = getResourceURL(knownResourceId);
775 String mediaType = MediaType.APPLICATION_XML;
776 final String entity = WRONG_XML_SCHEMA_DATA;
777 int statusCode = submitRequest(method, url, mediaType, entity);
779 // Check the status code of the response: does it match
780 // the expected response(s)?
781 if(logger.isDebugEnabled()){
782 logger.debug(testName + ": url=" + url +
783 " status=" + statusCode);
785 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
786 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
787 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
792 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateNonExistent(java.lang.String)
795 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
796 dependsOnMethods = {"update", "testSubmitRequest"})
797 public void updateNonExistent(String testName) throws Exception {
800 setupUpdateNonExistent(testName);
802 // Submit the request to the service and store the response.
804 // Note: The ID used in this 'create' call may be arbitrary.
805 // The only relevant ID may be the one used in updateCollectionObject(), below.
806 CollectionObjectClient client = new CollectionObjectClient();
807 MultipartOutput multipart =
808 createCollectionObjectInstance(client.getCommonPartName(),
810 ClientResponse<MultipartInput> res =
811 client.update(NON_EXISTENT_ID, multipart);
812 int statusCode = res.getStatus();
814 // Check the status code of the response: does it match
815 // the expected response(s)?
816 if (logger.isDebugEnabled()) {
817 logger.debug(testName + ": status = " + statusCode);
819 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
820 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
821 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
825 * Test how the service handles, in an Update request, payloads
826 * containing null values (or, in the case of String fields,
827 * empty String values) in one or more fields in which non-empty
828 * values are required.
830 * This is a test of code and/or configuration in the service's
831 * validation routine(s).
833 * @param testName The name of this test method. This name is supplied
834 * automatically, via reflection, by a TestNG 'data provider' in
838 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
839 dependsOnMethods = {"read"})
840 public void updateWithRequiredValuesNullOrEmpty(String testName) throws Exception {
842 setupUpdate(testName);
843 if (logger.isDebugEnabled()) {
844 logger.debug(testName + " got object to update with ID: " + knownResourceId);
847 // Read an existing record for updating.
848 ClientResponse<MultipartInput> res = updateRetrieve(testName, knownResourceId);
850 CollectionObjectClient client = new CollectionObjectClient();
851 MultipartInput input = (MultipartInput) res.getEntity();
852 CollectionobjectsCommon collectionObject =
853 (CollectionobjectsCommon) extractPart(input,
854 client.getCommonPartName(), CollectionobjectsCommon.class);
855 Assert.assertNotNull(collectionObject);
857 // Update with invalid content, by setting a value to the
858 // empty String, in a field that requires a non-empty value,
859 // as enforced by the service's validation routine(s).
860 collectionObject.setObjectNumber("");
862 if (logger.isDebugEnabled()) {
863 logger.debug(testName + " updated object");
864 logger.debug(objectAsXmlString(collectionObject,
865 CollectionobjectsCommon.class));
868 // Submit the request to the service and store the response.
869 res = updateSend(testName, knownResourceId, collectionObject);
870 int statusCode = res.getStatus();
872 // Read the response and verify that the update attempt failed.
873 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
874 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
875 Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
879 // ---------------------------------------------------------------
880 // CRUD tests : DELETE tests
881 // ---------------------------------------------------------------
884 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#delete(java.lang.String)
887 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
888 dependsOnMethods = {"create", "readList", "testSubmitRequest", "update"})
889 public void delete(String testName) throws Exception {
892 setupDelete(testName);
894 // Submit the request to the service and store the response.
895 CollectionObjectClient client = new CollectionObjectClient();
896 ClientResponse<Response> res = client.delete(knownResourceId);
897 int statusCode = res.getStatus();
899 // Check the status code of the response: does it match
900 // the expected response(s)?
901 if (logger.isDebugEnabled()) {
902 logger.debug(testName + ": status = " + statusCode);
904 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
905 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
906 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
911 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#deleteNonExistent(java.lang.String)
914 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
915 dependsOnMethods = {"delete"})
916 public void deleteNonExistent(String testName) throws Exception {
919 setupDeleteNonExistent(testName);
921 // Submit the request to the service and store the response.
922 CollectionObjectClient client = new CollectionObjectClient();
923 ClientResponse<Response> res = client.delete(NON_EXISTENT_ID);
924 int statusCode = res.getStatus();
926 // Check the status code of the response: does it match
927 // the expected response(s)?
928 if (logger.isDebugEnabled()) {
929 logger.debug(testName + ": status = " + statusCode);
931 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
932 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
933 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
936 // ---------------------------------------------------------------
937 // Utility tests : tests of code used in tests above
938 // ---------------------------------------------------------------
940 * Tests the code for manually submitting data that is used by several
941 * of the methods above.
945 @Test(dependsOnMethods = {"create", "read"})
946 public void testSubmitRequest() throws Exception {
947 testSubmitRequest(knownResourceId);
951 * Test submit request.
953 * @param resourceId the resource id
954 * @throws Exception the exception
956 private void testSubmitRequest(String resourceId) throws Exception {
958 // Expected status code: 200 OK
959 final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
961 // Submit the request to the service and store the response.
962 String method = ServiceRequestType.READ.httpMethodName();
963 String url = getResourceURL(resourceId);
964 int statusCode = submitRequest(method, url);
966 // Check the status code of the response: does it match
967 // the expected response(s)?
968 if (logger.isDebugEnabled()) {
969 logger.debug("testSubmitRequest: url=" + url
970 + " status=" + statusCode);
972 Assert.assertEquals(statusCode, EXPECTED_STATUS);
976 // ---------------------------------------------------------------
977 // Utility methods used by tests above
978 // ---------------------------------------------------------------
980 * Creates the collection object instance.
982 * @param commonPartName the common part name
983 * @param identifier the identifier
984 * @return the multipart output
986 private MultipartOutput createCollectionObjectInstance(String commonPartName,
988 return createCollectionObjectInstance(commonPartName,
989 "objectNumber-" + identifier,
990 "objectName-" + identifier);
994 * Creates the collection object instance.
996 * @param commonPartName the common part name
997 * @param objectNumber the object number
998 * @param objectName the object name
999 * @return the multipart output
1001 private MultipartOutput createCollectionObjectInstance(String commonPartName,
1002 String objectNumber, String objectName) {
1003 CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
1005 ResponsibleDepartmentList deptList = new ResponsibleDepartmentList();
1006 List<String> depts = deptList.getResponsibleDepartment();
1007 // @TODO Use properly formatted refNames for representative departments
1008 // in this example test record. The following are mere placeholders.
1009 depts.add("urn:org.collectionspace.services.department:Registrar");
1010 if (multivalue == true) {
1011 depts.add("urn:org.walkerart.department:Fine Art");
1014 // FIXME: REM - Can someone please document why we are toggling this
1017 multivalue = !multivalue;
1019 OtherNumberList otherNumList = new OtherNumberList();
1020 List<OtherNumber> otherNumbers = otherNumList.getOtherNumber();
1022 OtherNumber otherNumber1 = new OtherNumber();
1023 otherNumber1.setNumberValue("101." + objectName);
1024 otherNumber1.setNumberType("integer");
1025 otherNumbers.add(otherNumber1);
1027 OtherNumber otherNumber2 = new OtherNumber();
1028 otherNumber2.setNumberValue("101.502.23.456." + objectName);
1029 otherNumber2.setNumberType("ipaddress");
1030 otherNumbers.add(otherNumber2);
1032 //FIXME: Title does not need to be set.
1033 collectionObject.setTitle("atitle");
1034 collectionObject.setResponsibleDepartments(deptList);
1035 collectionObject.setObjectNumber(objectNumber);
1037 collectionObject.setOtherNumberList(otherNumList);
1038 collectionObject.setOtherNumber("urn:org.walkerart.id:123");
1040 collectionObject.setObjectName(objectName);
1041 collectionObject.setAge(""); //test for null string
1042 collectionObject.setBriefDescription("Papier mache bird cow mask with horns, "
1043 + "painted red with black and yellow spots. "
1044 + "Puerto Rico. ca. 8" high, 6" wide, projects 10" (with horns).");
1046 CollectionobjectsNaturalhistory conh = new CollectionobjectsNaturalhistory();
1047 conh.setNhString("test-string");
1049 conh.setNhLong(9999);
1052 MultipartOutput multipart = createCollectionObjectInstance(commonPartName, collectionObject, conh);
1057 * Creates the collection object instance.
1059 * @param commonPartName the common part name
1060 * @param collectionObject the collection object
1061 * @param conh the conh
1062 * @return the multipart output
1064 private MultipartOutput createCollectionObjectInstance(String commonPartName,
1065 CollectionobjectsCommon collectionObject, CollectionobjectsNaturalhistory conh) {
1067 MultipartOutput multipart = CollectionObjectFactory.createCollectionObjectInstance(
1068 commonPartName, collectionObject, getNHPartName(), conh);
1069 if (logger.isDebugEnabled()) {
1070 logger.debug("to be created, collectionobject common");
1071 logger.debug(objectAsXmlString(collectionObject,
1072 CollectionobjectsCommon.class));
1076 if (logger.isDebugEnabled()) {
1077 logger.debug("to be created, collectionobject nhistory");
1078 logger.debug(objectAsXmlString(conh,
1079 CollectionobjectsNaturalhistory.class));
1087 * createCollectionObjectInstanceFromXml uses JAXB unmarshaller to retrieve
1088 * collectionobject from given file
1089 * @param commonPartName
1090 * @param commonPartFileName
1094 private MultipartOutput createCollectionObjectInstanceFromXml(String testName, String commonPartName,
1095 String commonPartFileName) throws Exception {
1097 CollectionobjectsCommon collectionObject =
1098 (CollectionobjectsCommon) getObjectFromFile(CollectionobjectsCommon.class,
1099 commonPartFileName);
1100 MultipartOutput multipart = new MultipartOutput();
1101 OutputPart commonPart = multipart.addPart(collectionObject,
1102 MediaType.APPLICATION_XML_TYPE);
1103 commonPart.getHeaders().add("label", commonPartName);
1105 if (logger.isDebugEnabled()) {
1106 logger.debug(testName + " to be created, collectionobject common");
1107 logger.debug(objectAsXmlString(collectionObject,
1108 CollectionobjectsCommon.class));
1115 * createCollectionObjectInstanceFromRawXml uses stringified collectionobject
1116 * retrieve from given file
1117 * @param commonPartName
1118 * @param commonPartFileName
1122 private MultipartOutput createCollectionObjectInstanceFromRawXml(String testName, String commonPartName,
1123 String commonPartFileName) throws Exception {
1125 MultipartOutput multipart = new MultipartOutput();
1126 String stringObject = getXmlDocumentAsString(commonPartFileName);
1127 if (logger.isDebugEnabled()) {
1128 logger.debug(testName + " to be created, collectionobject common " + "\n" + stringObject);
1130 OutputPart commonPart = multipart.addPart(stringObject,
1131 MediaType.APPLICATION_XML_TYPE);
1132 commonPart.getHeaders().add("label", commonPartName);
1139 * Gets the nH part name.
1141 * @return the nH part name
1143 private String getNHPartName() {
1144 return "collectionobjects_naturalhistory";
1148 * Creates the from xml file.
1150 * @param testName the test name
1151 * @param fileName the file name
1152 * @param useJaxb the use jaxb
1153 * @return the string
1154 * @throws Exception the exception
1156 private String createFromXmlFile(String testName, String fileName, boolean useJaxb) throws Exception {
1157 // Perform setup, such as initializing the type of service request
1158 // (e.g. CREATE, DELETE), its valid and expected status codes, and
1159 // its associated HTTP method name (e.g. POST, DELETE).
1160 setupCreate(testName);
1162 MultipartOutput multipart = null;
1164 CollectionObjectClient client = new CollectionObjectClient();
1166 multipart = createCollectionObjectInstanceFromXml(testName,
1167 client.getCommonPartName(), fileName);
1169 multipart = createCollectionObjectInstanceFromRawXml(testName,
1170 client.getCommonPartName(), fileName);
1172 ClientResponse<Response> res = client.create(multipart);
1173 int statusCode = res.getStatus();
1175 if (logger.isDebugEnabled()) {
1176 logger.debug(testName + ": status = " + statusCode);
1178 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
1179 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
1180 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
1181 String newId = extractId(res);
1182 allResourceIdsCreated.add(newId);