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.AbstractServiceClientImpl;
31 import org.collectionspace.services.client.CollectionObjectClient;
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.jaxb.AbstractCommonList;
39 import org.jboss.resteasy.client.ClientResponse;
40 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
41 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
42 import org.jboss.resteasy.plugins.providers.multipart.OutputPart;
43 import org.testng.Assert;
44 import org.testng.annotations.AfterClass;
45 import org.testng.annotations.Test;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
51 * CollectionObjectServiceTest, carries out tests against a
52 * deployed and running CollectionObject Service.
54 * $LastChangedRevision$
57 public class CollectionObjectServiceTest extends AbstractServiceTestImpl {
60 private final Logger logger =
61 LoggerFactory.getLogger(CollectionObjectServiceTest.class);
62 // Instance variables specific to this test.
63 /** The known resource id. */
64 private String knownResourceId = null;
66 /** The all resource ids created. */
67 private List<String> allResourceIdsCreated = new ArrayList();
69 /** The multivalue. */
70 private boolean multivalue; //toggle
77 private Logger getLogger() {
82 * @see org.collectionspace.services.client.test.BaseServiceTest#getServicePathComponent()
85 protected String getServicePathComponent() {
86 return new CollectionObjectClient().getServicePathComponent();
90 * @see org.collectionspace.services.client.test.BaseServiceTest#getClientInstance()
93 protected CollectionSpaceClient getClientInstance() {
94 return new CollectionObjectClient();
98 * @see org.collectionspace.services.client.test.BaseServiceTest#getAbstractCommonList(org.jboss.resteasy.client.ClientResponse)
101 protected AbstractCommonList getAbstractCommonList(
102 ClientResponse<AbstractCommonList> response) {
103 return response.getEntity(CollectionobjectsCommonList.class);
106 // ---------------------------------------------------------------
107 // CRUD tests : CREATE tests
108 // ---------------------------------------------------------------
111 * @see org.collectionspace.services.client.test.ServiceTest#create(java.lang.String)
114 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
115 public void create(String testName) throws Exception {
117 // Perform setup, such as initializing the type of service request
118 // (e.g. CREATE, DELETE), its valid and expected status codes, and
119 // its associated HTTP method name (e.g. POST, DELETE).
120 setupCreate(testName);
122 // Submit the request to the service and store the response.
123 CollectionObjectClient client = new CollectionObjectClient();
124 String identifier = createIdentifier();
125 MultipartOutput multipart =
126 createCollectionObjectInstance(client.getCommonPartName(), identifier);
127 ClientResponse<Response> res = client.create(multipart);
128 int statusCode = res.getStatus();
130 // Check the status code of the response: does it match
131 // the expected response(s)?
134 // Does it fall within the set of valid status codes?
135 // Does it exactly match the expected status code?
136 if (logger.isDebugEnabled()) {
137 logger.debug(testName + ": status = " + statusCode);
139 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
140 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
141 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
143 // Store the ID returned from the first resource created
144 // for additional tests below.
145 if (knownResourceId == null) {
146 knownResourceId = extractId(res);
147 if (logger.isDebugEnabled()) {
148 logger.debug(testName + ": knownResourceId=" + knownResourceId);
152 // Store the IDs from every resource created by tests,
153 // so they can be deleted after tests have been run.
154 allResourceIdsCreated.add(extractId(res));
159 * Tests to diagnose and verify the fixed status of CSPACE-1026,
160 * "Whitespace at certain points in payload cause failure"
163 * Creates the from xml cambridge.
165 * @param testName the test name
166 * @throws Exception the exception
168 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
169 dependsOnMethods = {"create", "testSubmitRequest"})
170 public void createFromXmlCambridge(String testName) throws Exception {
172 createFromXmlFile(testName, "./test-data/testCambridge.xml", true);
173 testSubmitRequest(newId);
177 * Creates the from xml rfw s1.
179 * @param testName the test name
180 * @throws Exception the exception
182 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
183 dependsOnMethods = {"create", "testSubmitRequest"})
184 public void createFromXmlRFWS1(String testName) throws Exception {
185 String testDataDir = System.getProperty("test-data.fileName");
187 //createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp1.xml", false);
188 createFromXmlFile(testName, testDataDir + "/repfield_whitesp1.xml", false);
189 testSubmitRequest(newId);
193 * Creates the from xml rfw s2.
195 * @param testName the test name
196 * @throws Exception the exception
198 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
199 dependsOnMethods = {"create", "testSubmitRequest"})
200 public void createFromXmlRFWS2(String testName) throws Exception {
201 String testDataDir = System.getProperty("test-data.fileName");
203 //createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp2.xml", false);
204 createFromXmlFile(testName, testDataDir + "/repfield_whitesp2.xml", false);
205 testSubmitRequest(newId);
209 * Creates the from xml rfw s3.
211 * @param testName the test name
212 * @throws Exception the exception
214 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
215 dependsOnMethods = {"create", "testSubmitRequest"})
216 public void createFromXmlRFWS3(String testName) throws Exception {
217 String testDataDir = System.getProperty("test-data.fileName");
219 //createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp3.xml", false);
220 createFromXmlFile(testName, testDataDir + "/repfield_whitesp3.xml", false);
221 testSubmitRequest(newId);
225 * Creates the from xml rfw s4.
227 * @param testName the test name
228 * @throws Exception the exception
230 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
231 dependsOnMethods = {"create", "testSubmitRequest"})
232 public void createFromXmlRFWS4(String testName) throws Exception {
233 String testDataDir = System.getProperty("test-data.fileName");
235 createFromXmlFile(testName, testDataDir + "/repfield_whitesp4.xml", false);
236 testSubmitRequest(newId);
240 * Tests to diagnose and verify the fixed status of CSPACE-1248,
241 * "Wedged records created!" (i.e. records with child repeatable
242 * fields, which contain null values, can be successfully created
243 * but an error occurs on trying to retrieve those records).
246 * Creates the with null value repeatable field.
248 * @param testName the test name
249 * @throws Exception the exception
251 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
252 dependsOnMethods = {"create", "testSubmitRequest"})
253 public void createWithNullValueRepeatableField(String testName) throws Exception {
254 String testDataDir = System.getProperty("test-data.fileName");
256 createFromXmlFile(testName, testDataDir + "/repfield_null1.xml", false);
257 if (logger.isDebugEnabled()) {
258 logger.debug("Successfully created record with null value repeatable field.");
259 logger.debug("Attempting to retrieve just-created record ...");
261 testSubmitRequest(newId);
265 * @see org.collectionspace.services.client.test.ServiceTest#createList()
268 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
269 dependsOnMethods = {"create"})
270 public void createList(String testName) throws Exception {
271 for (int i = 0; i < DEFAULT_LIST_SIZE; i++) {
277 // Placeholders until the three tests below can be uncommented.
278 // See Issue CSPACE-401.
280 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#createWithEmptyEntityBody(java.lang.String)
283 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
284 public void createWithEmptyEntityBody(String testName) throws Exception {
288 * Test how the service handles XML that is not well formed,
289 * when sent in the payload of a Create request.
291 * @param testName The name of this test method. This name is supplied
292 * automatically, via reflection, by a TestNG 'data provider' in
296 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
297 public void createWithMalformedXml(String testName) throws Exception {
298 setupCreate(testName);
302 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#createWithWrongXmlSchema(java.lang.String)
305 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
306 public void createWithWrongXmlSchema(String testName) throws Exception {
312 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
313 dependsOnMethods = {"create", "testSubmitRequest"})
314 public void createWithEmptyEntityBody(String testName) throwsException {
317 setupCreateWithEmptyEntityBody(testName);
319 // Submit the request to the service and store the response.
320 String method = REQUEST_TYPE.httpMethodName();
321 String url = getServiceRootURL();
322 String mediaType = MediaType.APPLICATION_XML;
323 final String entity = "";
324 int statusCode = submitRequest(method, url, mediaType, entity);
326 // Check the status code of the response: does it match
327 // the expected response(s)?
328 if(logger.isDebugEnabled()){
329 logger.debug(testName + ": url=" + url +
330 " status=" + statusCode);
332 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
333 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
334 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
338 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
339 dependsOnMethods = {"create", "testSubmitRequest"})
340 public void createWithMalformedXml(String testName) throws Exception {
343 setupCreateWithMalformedXml(testName);
345 // Submit the request to the service and store the response.
346 String method = REQUEST_TYPE.httpMethodName();
347 String url = getServiceRootURL();
348 String mediaType = MediaType.APPLICATION_XML;
349 final String entity = MALFORMED_XML_DATA; // Constant from base class.
350 int statusCode = submitRequest(method, url, mediaType, entity);
352 // Check the status code of the response: does it match
353 // the expected response(s)?
354 if(logger.isDebugEnabled()){
355 logger.debug(testName + ": url=" + url +
356 " status=" + statusCode);
358 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
359 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
360 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
364 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
365 dependsOnMethods = {"create", "testSubmitRequest"})
366 public void createWithWrongXmlSchema(String testName) throws Exception {
369 setupCreateWithWrongXmlSchema(testName);
371 // Submit the request to the service and store the response.
372 String method = REQUEST_TYPE.httpMethodName();
373 String url = getServiceRootURL();
374 String mediaType = MediaType.APPLICATION_XML;
375 final String entity = WRONG_XML_SCHEMA_DATA;
376 int statusCode = submitRequest(method, url, mediaType, entity);
378 // Check the status code of the response: does it match
379 // the expected response(s)?
380 if(logger.isDebugEnabled()){
381 logger.debug(testName + ": url=" + url +
382 " status=" + statusCode);
384 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
385 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
386 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
391 * Test how the service handles, in a Create request, payloads
392 * containing null values (or, in the case of String fields,
393 * empty String values) in one or more fields which must be
394 * present and are required to contain non-empty values.
396 * This is a test of code and/or configuration in the service's
397 * validation routine(s).
399 * @param testName The name of this test method. This name is supplied
400 * automatically, via reflection, by a TestNG 'data provider' in
403 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
404 public void createWithRequiredValuesNullOrEmpty(String testName) throws Exception {
405 setupCreate(testName);
407 // Build a payload with invalid content, by omitting a
408 // field (objectNumber) which must be present, and in which
409 // a non-empty value is required, as enforced by the service's
410 // validation routine(s).
411 CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
412 collectionObject.setTitle("atitle");
413 collectionObject.setObjectName("some name");
415 // Submit the request to the service and store the response.
416 CollectionObjectClient client = new CollectionObjectClient();
417 MultipartOutput multipart =
418 createCollectionObjectInstance(client.getCommonPartName(), collectionObject, null);
419 ClientResponse<Response> res = client.create(multipart);
420 int statusCode = res.getStatus();
422 // Read the response and verify that the create attempt failed.
423 if (logger.isDebugEnabled()) {
424 logger.debug(testName + ": status = " + statusCode);
426 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
427 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
428 Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
430 // FIXME: Consider splitting off the following into its own test method.
432 // Build a payload with invalid content, by setting a value to the
433 // empty String, in a field that requires a non-empty value,
434 // as enforced by the service's validation routine(s).
435 collectionObject = new CollectionobjectsCommon();
436 collectionObject.setTitle("atitle");
437 collectionObject.setObjectName("some name");
438 collectionObject.setObjectNumber("");
440 // Submit the request to the service and store the response.
442 createCollectionObjectInstance(client.getCommonPartName(), collectionObject, null);
443 res = client.create(multipart);
444 statusCode = res.getStatus();
446 // Read the response and verify that the create attempt failed.
447 if (logger.isDebugEnabled()) {
448 logger.debug(testName + ": status = " + statusCode);
450 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
451 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
452 Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
457 // ---------------------------------------------------------------
458 // CRUD tests : READ tests
459 // ---------------------------------------------------------------
462 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#read(java.lang.String)
465 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
466 dependsOnMethods = {"create"})
467 public void read(String testName) throws Exception {
472 // Submit the request to the service and store the response.
473 CollectionObjectClient client = new CollectionObjectClient();
474 ClientResponse<MultipartInput> res = client.read(knownResourceId);
475 int statusCode = res.getStatus();
477 // Check the status code of the response: does it match
478 // the expected response(s)?
479 if (logger.isDebugEnabled()) {
480 logger.debug(testName + ": status = " + statusCode);
482 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
483 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
484 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
486 MultipartInput input = (MultipartInput) res.getEntity();
488 if (logger.isDebugEnabled()) {
489 logger.debug(testName + ": Reading Common part ...");
491 CollectionobjectsCommon collectionObject =
492 (CollectionobjectsCommon) extractPart(input,
493 client.getCommonPartName(), CollectionobjectsCommon.class);
494 Assert.assertNotNull(collectionObject);
496 if (logger.isDebugEnabled()) {
497 logger.debug(testName + ": Reading Natural History part ...");
499 CollectionobjectsNaturalhistory conh =
500 (CollectionobjectsNaturalhistory) extractPart(input,
501 getNHPartName(), CollectionobjectsNaturalhistory.class);
502 Assert.assertNotNull(conh);
507 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#readNonExistent(java.lang.String)
510 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
511 dependsOnMethods = {"read"})
512 public void readNonExistent(String testName) throws Exception {
515 setupReadNonExistent(testName);
517 // Submit the request to the service and store the response.
518 CollectionObjectClient client = new CollectionObjectClient();
519 ClientResponse<MultipartInput> res = client.read(NON_EXISTENT_ID);
520 int statusCode = res.getStatus();
522 // Check the status code of the response: does it match
523 // the expected response(s)?
524 if (logger.isDebugEnabled()) {
525 logger.debug(testName + ": status = " + statusCode);
527 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
528 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
529 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
533 // ---------------------------------------------------------------
534 // CRUD tests : READ_LIST tests
535 // ---------------------------------------------------------------
538 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#readList(java.lang.String)
541 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
542 dependsOnMethods = {"createList", "read"})
543 public void readList(String testName) throws Exception {
546 setupReadList(testName);
548 // Submit the request to the service and store the response.
549 CollectionObjectClient client = new CollectionObjectClient();
550 ClientResponse<CollectionobjectsCommonList> res = client.readList();
551 CollectionobjectsCommonList list = res.getEntity();
552 int statusCode = res.getStatus();
554 // Check the status code of the response: does it match
555 // the expected response(s)?
556 if (logger.isDebugEnabled()) {
557 logger.debug(testName + ": status = " + statusCode);
559 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
560 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
561 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
563 // Optionally output additional data about list members for debugging.
564 boolean iterateThroughList = false;
565 if (iterateThroughList && logger.isDebugEnabled()) {
566 List<CollectionobjectsCommonList.CollectionObjectListItem> items =
567 list.getCollectionObjectListItem();
570 for (CollectionobjectsCommonList.CollectionObjectListItem item : items) {
571 logger.debug(testName + ": list-item[" + i + "] csid="
573 logger.debug(testName + ": list-item[" + i + "] objectNumber="
574 + item.getObjectNumber());
575 logger.debug(testName + ": list-item[" + i + "] URI="
585 // ---------------------------------------------------------------
586 // CRUD tests : UPDATE tests
587 // ---------------------------------------------------------------
590 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#update(java.lang.String)
593 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
594 dependsOnMethods = {"read"})
595 public void update(String testName) throws Exception {
598 setupUpdate(testName);
600 // Read an existing resource that will be updated.
601 ClientResponse<MultipartInput> res = updateRetrieve(testName, knownResourceId);
603 // Extract its common part.
604 CollectionObjectClient client = new CollectionObjectClient();
605 MultipartInput input = (MultipartInput) res.getEntity();
606 CollectionobjectsCommon collectionObject =
607 (CollectionobjectsCommon) extractPart(input,
608 client.getCommonPartName(), CollectionobjectsCommon.class);
609 Assert.assertNotNull(collectionObject);
611 // Change the content of one or more fields in the common part.
612 collectionObject.setObjectNumber("updated-" + collectionObject.getObjectNumber());
613 collectionObject.setObjectName("updated-" + collectionObject.getObjectName());
614 if (logger.isDebugEnabled()) {
615 logger.debug("sparse update that will be sent in update request:");
616 logger.debug(objectAsXmlString(collectionObject,
617 CollectionobjectsCommon.class));
620 // Send the changed resource to be updated.
621 res = updateSend(testName, knownResourceId, collectionObject);
622 int statusCode = res.getStatus();
623 // Check the status code of the response: does it match the expected response(s)?
624 if (logger.isDebugEnabled()) {
625 logger.debug(testName + ": status = " + statusCode);
627 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
628 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
629 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
631 // Read the response and verify that the resource was correctly updated.
632 input = (MultipartInput) res.getEntity();
633 CollectionobjectsCommon updatedCollectionObject =
634 (CollectionobjectsCommon) extractPart(input,
635 client.getCommonPartName(), CollectionobjectsCommon.class);
636 Assert.assertNotNull(updatedCollectionObject);
637 Assert.assertEquals(updatedCollectionObject.getObjectName(),
638 collectionObject.getObjectName(),
639 "Data in updated object did not match submitted data.");
646 * @param testName the test name
648 * @return the client response
650 private ClientResponse<MultipartInput> updateRetrieve(String testName, String id) {
651 final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
652 CollectionObjectClient client = new CollectionObjectClient();
653 ClientResponse<MultipartInput> res = client.read(id);
654 if (logger.isDebugEnabled()) {
655 logger.debug("read in updateRetrieve for " + testName + " status = " + res.getStatus());
657 Assert.assertEquals(res.getStatus(), EXPECTED_STATUS);
658 if (logger.isDebugEnabled()) {
659 logger.debug("got object to updateRetrieve for " + testName + " with ID: " + id);
667 * @param testName the test name
669 * @param collectionObject the collection object
670 * @return the client response
672 private ClientResponse<MultipartInput> updateSend(String testName, String id,
673 CollectionobjectsCommon collectionObject) {
674 MultipartOutput output = new MultipartOutput();
675 OutputPart commonPart = output.addPart(collectionObject, MediaType.APPLICATION_XML_TYPE);
676 CollectionObjectClient client = new CollectionObjectClient();
677 commonPart.getHeaders().add("label", client.getCommonPartName());
678 ClientResponse<MultipartInput> res = client.update(knownResourceId, output);
683 // Placeholders until the three tests below can be uncommented.
684 // See Issue CSPACE-401.
686 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateWithEmptyEntityBody(java.lang.String)
689 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
690 dependsOnMethods = {"read"})
691 public void updateWithEmptyEntityBody(String testName) throws Exception {
695 * Test how the service handles XML that is not well formed,
696 * when sent in the payload of an Update request.
698 * @param testName The name of this test method. This name is supplied
699 * automatically, via reflection, by a TestNG 'data provider' in
703 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
704 dependsOnMethods = {"read"})
705 public void updateWithMalformedXml(String testName) throws Exception {
709 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateWithWrongXmlSchema(java.lang.String)
712 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
713 dependsOnMethods = {"read"})
714 public void updateWithWrongXmlSchema(String testName) throws Exception {
719 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
720 dependsOnMethods = {"create", "update", "testSubmitRequest"})
721 public void updateWithEmptyEntityBody(String testName) throws Exception {
724 setupUpdateWithEmptyEntityBody(testName);
726 // Submit the request to the service and store the response.
727 String method = REQUEST_TYPE.httpMethodName();
728 String url = getResourceURL(knownResourceId);
729 String mediaType = MediaType.APPLICATION_XML;
730 final String entity = "";
731 int statusCode = submitRequest(method, url, mediaType, entity);
733 // Check the status code of the response: does it match
734 // the expected response(s)?
735 if(logger.isDebugEnabled()){
736 logger.debug(testName + ": url=" + url +
737 " status=" + statusCode);
739 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
740 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
741 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
745 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
746 dependsOnMethods = {"create", "update", "testSubmitRequest"})
747 public void updateWithMalformedXml() throws Exception {
750 setupUpdateWithMalformedXml(testName);
752 // Submit the request to the service and store the response.
753 String method = REQUEST_TYPE.httpMethodName();
754 String url = getResourceURL(knownResourceId);
755 final String entity = MALFORMED_XML_DATA;
756 String mediaType = MediaType.APPLICATION_XML;
757 int statusCode = submitRequest(method, url, mediaType, entity);
759 // Check the status code of the response: does it match
760 // the expected response(s)?
761 if(logger.isDebugEnabled()){
762 logger.debug(testName + ": url=" + url +
763 " status=" + statusCode);
765 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
766 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
767 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
771 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
772 dependsOnMethods = {"create", "update", "testSubmitRequest"})
773 public void updateWithWrongXmlSchema(String testName) throws Exception {
776 setupUpdateWithWrongXmlSchema(String testName);
778 // Submit the request to the service and store the response.
779 String method = REQUEST_TYPE.httpMethodName();
780 String url = getResourceURL(knownResourceId);
781 String mediaType = MediaType.APPLICATION_XML;
782 final String entity = WRONG_XML_SCHEMA_DATA;
783 int statusCode = submitRequest(method, url, mediaType, entity);
785 // Check the status code of the response: does it match
786 // the expected response(s)?
787 if(logger.isDebugEnabled()){
788 logger.debug(testName + ": url=" + url +
789 " status=" + statusCode);
791 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
792 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
793 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
798 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateNonExistent(java.lang.String)
801 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
802 dependsOnMethods = {"update", "testSubmitRequest"})
803 public void updateNonExistent(String testName) throws Exception {
806 setupUpdateNonExistent(testName);
808 // Submit the request to the service and store the response.
810 // Note: The ID used in this 'create' call may be arbitrary.
811 // The only relevant ID may be the one used in updateCollectionObject(), below.
812 CollectionObjectClient client = new CollectionObjectClient();
813 MultipartOutput multipart =
814 createCollectionObjectInstance(client.getCommonPartName(),
816 ClientResponse<MultipartInput> res =
817 client.update(NON_EXISTENT_ID, multipart);
818 int statusCode = res.getStatus();
820 // Check the status code of the response: does it match
821 // the expected response(s)?
822 if (logger.isDebugEnabled()) {
823 logger.debug(testName + ": status = " + statusCode);
825 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
826 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
827 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
831 * Test how the service handles, in an Update request, payloads
832 * containing null values (or, in the case of String fields,
833 * empty String values) in one or more fields in which non-empty
834 * values are required.
836 * This is a test of code and/or configuration in the service's
837 * validation routine(s).
839 * @param testName The name of this test method. This name is supplied
840 * automatically, via reflection, by a TestNG 'data provider' in
843 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
844 dependsOnMethods = {"read"})
845 public void updateWithRequiredValuesNullOrEmpty(String testName) throws Exception {
847 setupUpdate(testName);
848 if (logger.isDebugEnabled()) {
849 logger.debug(testName + " got object to update with ID: " + knownResourceId);
852 // Read an existing record for updating.
853 ClientResponse<MultipartInput> res = updateRetrieve(testName, knownResourceId);
855 CollectionObjectClient client = new CollectionObjectClient();
856 MultipartInput input = (MultipartInput) res.getEntity();
857 CollectionobjectsCommon collectionObject =
858 (CollectionobjectsCommon) extractPart(input,
859 client.getCommonPartName(), CollectionobjectsCommon.class);
860 Assert.assertNotNull(collectionObject);
862 // Update with invalid content, by setting a value to the
863 // empty String, in a field that requires a non-empty value,
864 // as enforced by the service's validation routine(s).
865 collectionObject.setObjectNumber("");
867 if (logger.isDebugEnabled()) {
868 logger.debug(testName + " updated object");
869 logger.debug(objectAsXmlString(collectionObject,
870 CollectionobjectsCommon.class));
873 // Submit the request to the service and store the response.
874 res = updateSend(testName, knownResourceId, collectionObject);
875 int statusCode = res.getStatus();
877 // Read the response and verify that the update attempt failed.
878 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
879 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
880 Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
884 // ---------------------------------------------------------------
885 // CRUD tests : DELETE tests
886 // ---------------------------------------------------------------
889 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#delete(java.lang.String)
892 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
893 dependsOnMethods = {"create", "readList", "testSubmitRequest", "update"})
894 public void delete(String testName) throws Exception {
897 setupDelete(testName);
899 // Submit the request to the service and store the response.
900 CollectionObjectClient client = new CollectionObjectClient();
901 ClientResponse<Response> res = client.delete(knownResourceId);
902 int statusCode = res.getStatus();
904 // Check the status code of the response: does it match
905 // the expected response(s)?
906 if (logger.isDebugEnabled()) {
907 logger.debug(testName + ": status = " + statusCode);
909 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
910 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
911 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
916 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#deleteNonExistent(java.lang.String)
919 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
920 dependsOnMethods = {"delete"})
921 public void deleteNonExistent(String testName) throws Exception {
924 setupDeleteNonExistent(testName);
926 // Submit the request to the service and store the response.
927 CollectionObjectClient client = new CollectionObjectClient();
928 ClientResponse<Response> res = client.delete(NON_EXISTENT_ID);
929 int statusCode = res.getStatus();
931 // Check the status code of the response: does it match
932 // the expected response(s)?
933 if (logger.isDebugEnabled()) {
934 logger.debug(testName + ": status = " + statusCode);
936 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
937 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
938 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
941 // ---------------------------------------------------------------
942 // Utility tests : tests of code used in tests above
943 // ---------------------------------------------------------------
945 * Tests the code for manually submitting data that is used by several
946 * of the methods above.
949 @Test(dependsOnMethods = {"create", "read"})
950 public void testSubmitRequest() throws Exception {
951 testSubmitRequest(knownResourceId);
955 * Test submit request.
957 * @param resourceId the resource id
958 * @throws Exception the exception
960 private void testSubmitRequest(String resourceId) throws Exception {
962 // Expected status code: 200 OK
963 final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
965 // Submit the request to the service and store the response.
966 String method = ServiceRequestType.READ.httpMethodName();
967 String url = getResourceURL(resourceId);
968 int statusCode = submitRequest(method, url);
970 // Check the status code of the response: does it match
971 // the expected response(s)?
972 if (logger.isDebugEnabled()) {
973 logger.debug("testSubmitRequest: url=" + url
974 + " status=" + statusCode);
976 Assert.assertEquals(statusCode, EXPECTED_STATUS);
980 // ---------------------------------------------------------------
981 // Cleanup of resources created during testing
982 // ---------------------------------------------------------------
984 * Deletes all resources created by tests, after all tests have been run.
986 * This cleanup method will always be run, even if one or more tests fail.
987 * For this reason, it attempts to remove all resources created
988 * at any point during testing, even if some of those resources
989 * may be expected to be deleted by certain tests.
991 @AfterClass(alwaysRun = true)
992 public void cleanUp() {
993 String noTest = System.getProperty("noTestCleanup");
994 if(Boolean.TRUE.toString().equalsIgnoreCase(noTest)) {
995 if (logger.isDebugEnabled()) {
996 logger.debug("Skipping Cleanup phase ...");
1000 if (logger.isDebugEnabled()) {
1001 logger.debug("Cleaning up temporary resources created for testing ...");
1003 CollectionObjectClient client = new CollectionObjectClient();
1004 for (String resourceId : allResourceIdsCreated) {
1005 // Note: Any non-success responses are ignored and not reported.
1006 ClientResponse<Response> res = client.delete(resourceId);
1010 // ---------------------------------------------------------------
1011 // Utility methods used by tests above
1012 // ---------------------------------------------------------------
1014 * Creates the collection object instance.
1016 * @param commonPartName the common part name
1017 * @param identifier the identifier
1018 * @return the multipart output
1020 private MultipartOutput createCollectionObjectInstance(String commonPartName,
1021 String identifier) {
1022 return createCollectionObjectInstance(commonPartName,
1023 "objectNumber-" + identifier,
1024 "objectName-" + identifier);
1028 * Creates the collection object instance.
1030 * @param commonPartName the common part name
1031 * @param objectNumber the object number
1032 * @param objectName the object name
1033 * @return the multipart output
1035 private MultipartOutput createCollectionObjectInstance(String commonPartName,
1036 String objectNumber, String objectName) {
1037 CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
1038 ResponsibleDepartmentList deptList = new ResponsibleDepartmentList();
1039 List<String> depts = deptList.getResponsibleDepartment();
1040 // @TODO Use properly formatted refNames for representative departments
1041 // in this example test record. The following are mere placeholders.
1042 depts.add("urn:org.collectionspace.services.department:Registrar");
1044 depts.add("urn:org.walkerart.department:Fine Art");
1046 multivalue = !multivalue;
1047 //FIXME: Title does not need to be set.
1048 collectionObject.setTitle("atitle");
1049 collectionObject.setResponsibleDepartments(deptList);
1050 collectionObject.setObjectNumber(objectNumber);
1051 collectionObject.setOtherNumber("urn:org.walkerart.id:123");
1052 collectionObject.setObjectName(objectName);
1053 collectionObject.setAge(""); //test for null string
1054 collectionObject.setBriefDescription("Papier mache bird cow mask with horns, "
1055 + "painted red with black and yellow spots. "
1056 + "Puerto Rico. ca. 8" high, 6" wide, projects 10" (with horns).");
1058 CollectionobjectsNaturalhistory conh = new CollectionobjectsNaturalhistory();
1059 conh.setNhString("test-string");
1061 conh.setNhLong(9999);
1064 MultipartOutput multipart = createCollectionObjectInstance(commonPartName, collectionObject, conh);
1069 * Creates the collection object instance.
1071 * @param commonPartName the common part name
1072 * @param collectionObject the collection object
1073 * @param conh the conh
1074 * @return the multipart output
1076 private MultipartOutput createCollectionObjectInstance(String commonPartName,
1077 CollectionobjectsCommon collectionObject, CollectionobjectsNaturalhistory conh) {
1079 MultipartOutput multipart = new MultipartOutput();
1080 OutputPart commonPart = multipart.addPart(collectionObject,
1081 MediaType.APPLICATION_XML_TYPE);
1082 commonPart.getHeaders().add("label", commonPartName);
1084 if (logger.isDebugEnabled()) {
1085 logger.debug("to be created, collectionobject common");
1086 logger.debug(objectAsXmlString(collectionObject,
1087 CollectionobjectsCommon.class));
1091 OutputPart nhPart = multipart.addPart(conh, MediaType.APPLICATION_XML_TYPE);
1092 nhPart.getHeaders().add("label", getNHPartName());
1094 if (logger.isDebugEnabled()) {
1095 logger.debug("to be created, collectionobject nhistory");
1096 logger.debug(objectAsXmlString(conh,
1097 CollectionobjectsNaturalhistory.class));
1105 * createCollectionObjectInstanceFromXml uses JAXB unmarshaller to retrieve
1106 * collectionobject from given file
1107 * @param commonPartName
1108 * @param commonPartFileName
1112 private MultipartOutput createCollectionObjectInstanceFromXml(String testName, String commonPartName,
1113 String commonPartFileName) throws Exception {
1115 CollectionobjectsCommon collectionObject =
1116 (CollectionobjectsCommon) getObjectFromFile(CollectionobjectsCommon.class,
1117 commonPartFileName);
1118 MultipartOutput multipart = new MultipartOutput();
1119 OutputPart commonPart = multipart.addPart(collectionObject,
1120 MediaType.APPLICATION_XML_TYPE);
1121 commonPart.getHeaders().add("label", commonPartName);
1123 if (logger.isDebugEnabled()) {
1124 logger.debug(testName + " to be created, collectionobject common");
1125 logger.debug(objectAsXmlString(collectionObject,
1126 CollectionobjectsCommon.class));
1133 * createCollectionObjectInstanceFromRawXml uses stringified collectionobject
1134 * retrieve from given file
1135 * @param commonPartName
1136 * @param commonPartFileName
1140 private MultipartOutput createCollectionObjectInstanceFromRawXml(String testName, String commonPartName,
1141 String commonPartFileName) throws Exception {
1143 MultipartOutput multipart = new MultipartOutput();
1144 String stringObject = getXmlDocumentAsString(commonPartFileName);
1145 if (logger.isDebugEnabled()) {
1146 logger.debug(testName + " to be created, collectionobject common " + "\n" + stringObject);
1148 OutputPart commonPart = multipart.addPart(stringObject,
1149 MediaType.APPLICATION_XML_TYPE);
1150 commonPart.getHeaders().add("label", commonPartName);
1157 * Gets the nH part name.
1159 * @return the nH part name
1161 private String getNHPartName() {
1162 return "collectionobjects_naturalhistory";
1166 * Creates the from xml file.
1168 * @param testName the test name
1169 * @param fileName the file name
1170 * @param useJaxb the use jaxb
1171 * @return the string
1172 * @throws Exception the exception
1174 private String createFromXmlFile(String testName, String fileName, boolean useJaxb) throws Exception {
1175 // Perform setup, such as initializing the type of service request
1176 // (e.g. CREATE, DELETE), its valid and expected status codes, and
1177 // its associated HTTP method name (e.g. POST, DELETE).
1178 setupCreate(testName);
1180 MultipartOutput multipart = null;
1182 CollectionObjectClient client = new CollectionObjectClient();
1184 multipart = createCollectionObjectInstanceFromXml(testName,
1185 client.getCommonPartName(), fileName);
1187 multipart = createCollectionObjectInstanceFromRawXml(testName,
1188 client.getCommonPartName(), fileName);
1190 ClientResponse<Response> res = client.create(multipart);
1191 int statusCode = res.getStatus();
1193 if (logger.isDebugEnabled()) {
1194 logger.debug(testName + ": status = " + statusCode);
1196 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
1197 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
1198 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
1199 String newId = extractId(res);
1200 allResourceIdsCreated.add(newId);