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<String>();
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 this.createPaginatedList(testName, DEFAULT_LIST_SIZE);
275 // Placeholders until the three tests below can be uncommented.
276 // See Issue CSPACE-401.
278 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#createWithEmptyEntityBody(java.lang.String)
281 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
282 public void createWithEmptyEntityBody(String testName) throws Exception {
283 //FIXME: Should this test really be empty?
287 * Test how the service handles XML that is not well formed,
288 * when sent in the payload of a Create request.
290 * @param testName The name of this test method. This name is supplied
291 * automatically, via reflection, by a TestNG 'data provider' in
295 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
296 public void createWithMalformedXml(String testName) throws Exception {
297 setupCreate(testName);
301 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#createWithWrongXmlSchema(java.lang.String)
304 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
305 public void createWithWrongXmlSchema(String testName) throws Exception {
306 //FIXME: Should this test really be empty?
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
404 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
405 public void createWithRequiredValuesNullOrEmpty(String testName) throws Exception {
406 setupCreate(testName);
408 // Build a payload with invalid content, by omitting a
409 // field (objectNumber) which must be present, and in which
410 // a non-empty value is required, as enforced by the service's
411 // validation routine(s).
412 CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
413 collectionObject.setTitle("atitle");
414 collectionObject.setObjectName("some name");
416 // Submit the request to the service and store the response.
417 CollectionObjectClient client = new CollectionObjectClient();
418 MultipartOutput multipart =
419 createCollectionObjectInstance(client.getCommonPartName(), collectionObject, null);
420 ClientResponse<Response> res = client.create(multipart);
421 int statusCode = res.getStatus();
423 // Read the response and verify that the create attempt failed.
424 if (logger.isDebugEnabled()) {
425 logger.debug(testName + ": status = " + statusCode);
427 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
428 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
429 Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
431 // FIXME: Consider splitting off the following into its own test method.
433 // Build a payload with invalid content, by setting a value to the
434 // empty String, in a field that requires a non-empty value,
435 // as enforced by the service's validation routine(s).
436 collectionObject = new CollectionobjectsCommon();
437 collectionObject.setTitle("atitle");
438 collectionObject.setObjectName("some name");
439 collectionObject.setObjectNumber("");
441 // Submit the request to the service and store the response.
443 createCollectionObjectInstance(client.getCommonPartName(), collectionObject, null);
444 res = client.create(multipart);
445 statusCode = res.getStatus();
447 // Read the response and verify that the create attempt failed.
448 if (logger.isDebugEnabled()) {
449 logger.debug(testName + ": status = " + statusCode);
451 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
452 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
453 Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
458 // ---------------------------------------------------------------
459 // CRUD tests : READ tests
460 // ---------------------------------------------------------------
463 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#read(java.lang.String)
466 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
467 dependsOnMethods = {"create"})
468 public void read(String testName) throws Exception {
473 // Submit the request to the service and store the response.
474 CollectionObjectClient client = new CollectionObjectClient();
475 ClientResponse<MultipartInput> res = client.read(knownResourceId);
476 int statusCode = res.getStatus();
478 // Check the status code of the response: does it match
479 // the expected response(s)?
480 if (logger.isDebugEnabled()) {
481 logger.debug(testName + ": status = " + statusCode);
483 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
484 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
485 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
487 MultipartInput input = (MultipartInput) res.getEntity();
489 if (logger.isDebugEnabled()) {
490 logger.debug(testName + ": Reading Common part ...");
492 CollectionobjectsCommon collectionObject =
493 (CollectionobjectsCommon) extractPart(input,
494 client.getCommonPartName(), CollectionobjectsCommon.class);
495 Assert.assertNotNull(collectionObject);
497 if (logger.isDebugEnabled()) {
498 logger.debug(testName + ": Reading Natural History part ...");
500 CollectionobjectsNaturalhistory conh =
501 (CollectionobjectsNaturalhistory) extractPart(input,
502 getNHPartName(), CollectionobjectsNaturalhistory.class);
503 Assert.assertNotNull(conh);
508 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#readNonExistent(java.lang.String)
511 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
512 dependsOnMethods = {"read"})
513 public void readNonExistent(String testName) throws Exception {
516 setupReadNonExistent(testName);
518 // Submit the request to the service and store the response.
519 CollectionObjectClient client = new CollectionObjectClient();
520 ClientResponse<MultipartInput> res = client.read(NON_EXISTENT_ID);
521 int statusCode = res.getStatus();
523 // Check the status code of the response: does it match
524 // the expected response(s)?
525 if (logger.isDebugEnabled()) {
526 logger.debug(testName + ": status = " + statusCode);
528 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
529 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
530 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
534 // ---------------------------------------------------------------
535 // CRUD tests : READ_LIST tests
536 // ---------------------------------------------------------------
539 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#readList(java.lang.String)
542 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
543 dependsOnMethods = {"createList", "read"})
544 public void readList(String testName) throws Exception {
547 setupReadList(testName);
549 // Submit the request to the service and store the response.
550 CollectionObjectClient client = new CollectionObjectClient();
551 ClientResponse<CollectionobjectsCommonList> res = client.readList();
552 CollectionobjectsCommonList list = res.getEntity();
553 int statusCode = res.getStatus();
555 // Check the status code of the response: does it match
556 // the expected response(s)?
557 if (logger.isDebugEnabled()) {
558 logger.debug(testName + ": status = " + statusCode);
560 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
561 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
562 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
564 // Optionally output additional data about list members for debugging.
565 boolean iterateThroughList = false;
566 if (iterateThroughList && logger.isDebugEnabled()) {
567 List<CollectionobjectsCommonList.CollectionObjectListItem> items =
568 list.getCollectionObjectListItem();
571 for (CollectionobjectsCommonList.CollectionObjectListItem item : items) {
572 logger.debug(testName + ": list-item[" + i + "] csid="
574 logger.debug(testName + ": list-item[" + i + "] objectNumber="
575 + item.getObjectNumber());
576 logger.debug(testName + ": list-item[" + i + "] URI="
586 // ---------------------------------------------------------------
587 // CRUD tests : UPDATE tests
588 // ---------------------------------------------------------------
591 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#update(java.lang.String)
594 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
595 dependsOnMethods = {"read"})
596 public void update(String testName) throws Exception {
599 setupUpdate(testName);
601 // Read an existing resource that will be updated.
602 ClientResponse<MultipartInput> res = updateRetrieve(testName, knownResourceId);
604 // Extract its common part.
605 CollectionObjectClient client = new CollectionObjectClient();
606 MultipartInput input = (MultipartInput) res.getEntity();
607 CollectionobjectsCommon collectionObject =
608 (CollectionobjectsCommon) extractPart(input,
609 client.getCommonPartName(), CollectionobjectsCommon.class);
610 Assert.assertNotNull(collectionObject);
612 // Change the content of one or more fields in the common part.
613 collectionObject.setObjectNumber("updated-" + collectionObject.getObjectNumber());
614 collectionObject.setObjectName("updated-" + collectionObject.getObjectName());
615 if (logger.isDebugEnabled()) {
616 logger.debug("sparse update that will be sent in update request:");
617 logger.debug(objectAsXmlString(collectionObject,
618 CollectionobjectsCommon.class));
621 // Send the changed resource to be updated.
622 res = updateSend(testName, knownResourceId, collectionObject);
623 int statusCode = res.getStatus();
624 // Check the status code of the response: does it match the expected response(s)?
625 if (logger.isDebugEnabled()) {
626 logger.debug(testName + ": status = " + statusCode);
628 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
629 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
630 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
632 // Read the response and verify that the resource was correctly updated.
633 input = (MultipartInput) res.getEntity();
634 CollectionobjectsCommon updatedCollectionObject =
635 (CollectionobjectsCommon) extractPart(input,
636 client.getCommonPartName(), CollectionobjectsCommon.class);
637 Assert.assertNotNull(updatedCollectionObject);
638 Assert.assertEquals(updatedCollectionObject.getObjectName(),
639 collectionObject.getObjectName(),
640 "Data in updated object did not match submitted data.");
647 * @param testName the test name
649 * @return the client response
651 private ClientResponse<MultipartInput> updateRetrieve(String testName, String id) {
652 final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
653 CollectionObjectClient client = new CollectionObjectClient();
654 ClientResponse<MultipartInput> res = client.read(id);
655 if (logger.isDebugEnabled()) {
656 logger.debug("read in updateRetrieve for " + testName + " status = " + res.getStatus());
658 Assert.assertEquals(res.getStatus(), EXPECTED_STATUS);
659 if (logger.isDebugEnabled()) {
660 logger.debug("got object to updateRetrieve for " + testName + " with ID: " + id);
668 * @param testName the test name
670 * @param collectionObject the collection object
671 * @return the client response
673 private ClientResponse<MultipartInput> updateSend(String testName, String id,
674 CollectionobjectsCommon collectionObject) {
675 MultipartOutput output = new MultipartOutput();
676 OutputPart commonPart = output.addPart(collectionObject, MediaType.APPLICATION_XML_TYPE);
677 CollectionObjectClient client = new CollectionObjectClient();
678 commonPart.getHeaders().add("label", client.getCommonPartName());
679 ClientResponse<MultipartInput> res = client.update(knownResourceId, output);
684 // Placeholders until the three tests below can be uncommented.
685 // See Issue CSPACE-401.
687 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateWithEmptyEntityBody(java.lang.String)
690 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
691 dependsOnMethods = {"read"})
692 public void updateWithEmptyEntityBody(String testName) throws Exception {
693 //FIXME: Should this test really be empty?
697 * Test how the service handles XML that is not well formed,
698 * when sent in the payload of an Update request.
700 * @param testName The name of this test method. This name is supplied
701 * automatically, via reflection, by a TestNG 'data provider' in
705 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
706 dependsOnMethods = {"read"})
707 public void updateWithMalformedXml(String testName) throws Exception {
708 //FIXME: Should this test really be empty?
712 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateWithWrongXmlSchema(java.lang.String)
715 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
716 dependsOnMethods = {"read"})
717 public void updateWithWrongXmlSchema(String testName) throws Exception {
718 //FIXME: Should this test really be empty?
723 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
724 dependsOnMethods = {"create", "update", "testSubmitRequest"})
725 public void updateWithEmptyEntityBody(String testName) throws Exception {
728 setupUpdateWithEmptyEntityBody(testName);
730 // Submit the request to the service and store the response.
731 String method = REQUEST_TYPE.httpMethodName();
732 String url = getResourceURL(knownResourceId);
733 String mediaType = MediaType.APPLICATION_XML;
734 final String entity = "";
735 int statusCode = submitRequest(method, url, mediaType, entity);
737 // Check the status code of the response: does it match
738 // the expected response(s)?
739 if(logger.isDebugEnabled()){
740 logger.debug(testName + ": url=" + url +
741 " status=" + statusCode);
743 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
744 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
745 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
749 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
750 dependsOnMethods = {"create", "update", "testSubmitRequest"})
751 public void updateWithMalformedXml() throws Exception {
754 setupUpdateWithMalformedXml(testName);
756 // Submit the request to the service and store the response.
757 String method = REQUEST_TYPE.httpMethodName();
758 String url = getResourceURL(knownResourceId);
759 final String entity = MALFORMED_XML_DATA;
760 String mediaType = MediaType.APPLICATION_XML;
761 int statusCode = submitRequest(method, url, mediaType, entity);
763 // Check the status code of the response: does it match
764 // the expected response(s)?
765 if(logger.isDebugEnabled()){
766 logger.debug(testName + ": url=" + url +
767 " status=" + statusCode);
769 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
770 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
771 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
775 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
776 dependsOnMethods = {"create", "update", "testSubmitRequest"})
777 public void updateWithWrongXmlSchema(String testName) throws Exception {
780 setupUpdateWithWrongXmlSchema(String testName);
782 // Submit the request to the service and store the response.
783 String method = REQUEST_TYPE.httpMethodName();
784 String url = getResourceURL(knownResourceId);
785 String mediaType = MediaType.APPLICATION_XML;
786 final String entity = WRONG_XML_SCHEMA_DATA;
787 int statusCode = submitRequest(method, url, mediaType, entity);
789 // Check the status code of the response: does it match
790 // the expected response(s)?
791 if(logger.isDebugEnabled()){
792 logger.debug(testName + ": url=" + url +
793 " status=" + statusCode);
795 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
796 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
797 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
802 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateNonExistent(java.lang.String)
805 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
806 dependsOnMethods = {"update", "testSubmitRequest"})
807 public void updateNonExistent(String testName) throws Exception {
810 setupUpdateNonExistent(testName);
812 // Submit the request to the service and store the response.
814 // Note: The ID used in this 'create' call may be arbitrary.
815 // The only relevant ID may be the one used in updateCollectionObject(), below.
816 CollectionObjectClient client = new CollectionObjectClient();
817 MultipartOutput multipart =
818 createCollectionObjectInstance(client.getCommonPartName(),
820 ClientResponse<MultipartInput> res =
821 client.update(NON_EXISTENT_ID, multipart);
822 int statusCode = res.getStatus();
824 // Check the status code of the response: does it match
825 // the expected response(s)?
826 if (logger.isDebugEnabled()) {
827 logger.debug(testName + ": status = " + statusCode);
829 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
830 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
831 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
835 * Test how the service handles, in an Update request, payloads
836 * containing null values (or, in the case of String fields,
837 * empty String values) in one or more fields in which non-empty
838 * values are required.
840 * This is a test of code and/or configuration in the service's
841 * validation routine(s).
843 * @param testName The name of this test method. This name is supplied
844 * automatically, via reflection, by a TestNG 'data provider' in
848 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
849 dependsOnMethods = {"read"})
850 public void updateWithRequiredValuesNullOrEmpty(String testName) throws Exception {
852 setupUpdate(testName);
853 if (logger.isDebugEnabled()) {
854 logger.debug(testName + " got object to update with ID: " + knownResourceId);
857 // Read an existing record for updating.
858 ClientResponse<MultipartInput> res = updateRetrieve(testName, knownResourceId);
860 CollectionObjectClient client = new CollectionObjectClient();
861 MultipartInput input = (MultipartInput) res.getEntity();
862 CollectionobjectsCommon collectionObject =
863 (CollectionobjectsCommon) extractPart(input,
864 client.getCommonPartName(), CollectionobjectsCommon.class);
865 Assert.assertNotNull(collectionObject);
867 // Update with invalid content, by setting a value to the
868 // empty String, in a field that requires a non-empty value,
869 // as enforced by the service's validation routine(s).
870 collectionObject.setObjectNumber("");
872 if (logger.isDebugEnabled()) {
873 logger.debug(testName + " updated object");
874 logger.debug(objectAsXmlString(collectionObject,
875 CollectionobjectsCommon.class));
878 // Submit the request to the service and store the response.
879 res = updateSend(testName, knownResourceId, collectionObject);
880 int statusCode = res.getStatus();
882 // Read the response and verify that the update attempt failed.
883 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
884 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
885 Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
889 // ---------------------------------------------------------------
890 // CRUD tests : DELETE tests
891 // ---------------------------------------------------------------
894 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#delete(java.lang.String)
897 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
898 dependsOnMethods = {"create", "readList", "testSubmitRequest", "update"})
899 public void delete(String testName) throws Exception {
902 setupDelete(testName);
904 // Submit the request to the service and store the response.
905 CollectionObjectClient client = new CollectionObjectClient();
906 ClientResponse<Response> res = client.delete(knownResourceId);
907 int statusCode = res.getStatus();
909 // Check the status code of the response: does it match
910 // the expected response(s)?
911 if (logger.isDebugEnabled()) {
912 logger.debug(testName + ": status = " + statusCode);
914 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
915 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
916 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
921 * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#deleteNonExistent(java.lang.String)
924 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
925 dependsOnMethods = {"delete"})
926 public void deleteNonExistent(String testName) throws Exception {
929 setupDeleteNonExistent(testName);
931 // Submit the request to the service and store the response.
932 CollectionObjectClient client = new CollectionObjectClient();
933 ClientResponse<Response> res = client.delete(NON_EXISTENT_ID);
934 int statusCode = res.getStatus();
936 // Check the status code of the response: does it match
937 // the expected response(s)?
938 if (logger.isDebugEnabled()) {
939 logger.debug(testName + ": status = " + statusCode);
941 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
942 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
943 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
946 // ---------------------------------------------------------------
947 // Utility tests : tests of code used in tests above
948 // ---------------------------------------------------------------
950 * Tests the code for manually submitting data that is used by several
951 * of the methods above.
955 @Test(dependsOnMethods = {"create", "read"})
956 public void testSubmitRequest() throws Exception {
957 testSubmitRequest(knownResourceId);
961 * Test submit request.
963 * @param resourceId the resource id
964 * @throws Exception the exception
966 private void testSubmitRequest(String resourceId) throws Exception {
968 // Expected status code: 200 OK
969 final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
971 // Submit the request to the service and store the response.
972 String method = ServiceRequestType.READ.httpMethodName();
973 String url = getResourceURL(resourceId);
974 int statusCode = submitRequest(method, url);
976 // Check the status code of the response: does it match
977 // the expected response(s)?
978 if (logger.isDebugEnabled()) {
979 logger.debug("testSubmitRequest: url=" + url
980 + " status=" + statusCode);
982 Assert.assertEquals(statusCode, EXPECTED_STATUS);
986 // ---------------------------------------------------------------
987 // Cleanup of resources created during testing
988 // ---------------------------------------------------------------
990 * Deletes all resources created by tests, after all tests have been run.
992 * This cleanup method will always be run, even if one or more tests fail.
993 * For this reason, it attempts to remove all resources created
994 * at any point during testing, even if some of those resources
995 * may be expected to be deleted by certain tests.
997 @AfterClass(alwaysRun = true)
998 public void cleanUp() {
999 String noTest = System.getProperty("noTestCleanup");
1000 if(Boolean.TRUE.toString().equalsIgnoreCase(noTest)) {
1001 if (logger.isDebugEnabled()) {
1002 logger.debug("Skipping Cleanup phase ...");
1006 if (logger.isDebugEnabled()) {
1007 logger.debug("Cleaning up temporary resources created for testing ...");
1009 CollectionObjectClient client = new CollectionObjectClient();
1010 for (String resourceId : allResourceIdsCreated) {
1011 // Note: Any non-success responses are ignored and not reported.
1012 ClientResponse<Response> res = client.delete(resourceId);
1016 // ---------------------------------------------------------------
1017 // Utility methods used by tests above
1018 // ---------------------------------------------------------------
1020 * Creates the collection object instance.
1022 * @param commonPartName the common part name
1023 * @param identifier the identifier
1024 * @return the multipart output
1026 private MultipartOutput createCollectionObjectInstance(String commonPartName,
1027 String identifier) {
1028 return createCollectionObjectInstance(commonPartName,
1029 "objectNumber-" + identifier,
1030 "objectName-" + identifier);
1034 * Creates the collection object instance.
1036 * @param commonPartName the common part name
1037 * @param objectNumber the object number
1038 * @param objectName the object name
1039 * @return the multipart output
1041 private MultipartOutput createCollectionObjectInstance(String commonPartName,
1042 String objectNumber, String objectName) {
1043 CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
1044 ResponsibleDepartmentList deptList = new ResponsibleDepartmentList();
1045 List<String> depts = deptList.getResponsibleDepartment();
1046 // @TODO Use properly formatted refNames for representative departments
1047 // in this example test record. The following are mere placeholders.
1048 depts.add("urn:org.collectionspace.services.department:Registrar");
1050 depts.add("urn:org.walkerart.department:Fine Art");
1052 multivalue = !multivalue;
1053 //FIXME: Title does not need to be set.
1054 collectionObject.setTitle("atitle");
1055 collectionObject.setResponsibleDepartments(deptList);
1056 collectionObject.setObjectNumber(objectNumber);
1057 collectionObject.setOtherNumber("urn:org.walkerart.id:123");
1058 collectionObject.setObjectName(objectName);
1059 collectionObject.setAge(""); //test for null string
1060 collectionObject.setBriefDescription("Papier mache bird cow mask with horns, "
1061 + "painted red with black and yellow spots. "
1062 + "Puerto Rico. ca. 8" high, 6" wide, projects 10" (with horns).");
1064 CollectionobjectsNaturalhistory conh = new CollectionobjectsNaturalhistory();
1065 conh.setNhString("test-string");
1067 conh.setNhLong(9999);
1070 MultipartOutput multipart = createCollectionObjectInstance(commonPartName, collectionObject, conh);
1075 * Creates the collection object instance.
1077 * @param commonPartName the common part name
1078 * @param collectionObject the collection object
1079 * @param conh the conh
1080 * @return the multipart output
1082 private MultipartOutput createCollectionObjectInstance(String commonPartName,
1083 CollectionobjectsCommon collectionObject, CollectionobjectsNaturalhistory conh) {
1085 MultipartOutput multipart = new MultipartOutput();
1086 OutputPart commonPart = multipart.addPart(collectionObject,
1087 MediaType.APPLICATION_XML_TYPE);
1088 commonPart.getHeaders().add("label", commonPartName);
1090 if (logger.isDebugEnabled()) {
1091 logger.debug("to be created, collectionobject common");
1092 logger.debug(objectAsXmlString(collectionObject,
1093 CollectionobjectsCommon.class));
1097 OutputPart nhPart = multipart.addPart(conh, MediaType.APPLICATION_XML_TYPE);
1098 nhPart.getHeaders().add("label", getNHPartName());
1100 if (logger.isDebugEnabled()) {
1101 logger.debug("to be created, collectionobject nhistory");
1102 logger.debug(objectAsXmlString(conh,
1103 CollectionobjectsNaturalhistory.class));
1111 * createCollectionObjectInstanceFromXml uses JAXB unmarshaller to retrieve
1112 * collectionobject from given file
1113 * @param commonPartName
1114 * @param commonPartFileName
1118 private MultipartOutput createCollectionObjectInstanceFromXml(String testName, String commonPartName,
1119 String commonPartFileName) throws Exception {
1121 CollectionobjectsCommon collectionObject =
1122 (CollectionobjectsCommon) getObjectFromFile(CollectionobjectsCommon.class,
1123 commonPartFileName);
1124 MultipartOutput multipart = new MultipartOutput();
1125 OutputPart commonPart = multipart.addPart(collectionObject,
1126 MediaType.APPLICATION_XML_TYPE);
1127 commonPart.getHeaders().add("label", commonPartName);
1129 if (logger.isDebugEnabled()) {
1130 logger.debug(testName + " to be created, collectionobject common");
1131 logger.debug(objectAsXmlString(collectionObject,
1132 CollectionobjectsCommon.class));
1139 * createCollectionObjectInstanceFromRawXml uses stringified collectionobject
1140 * retrieve from given file
1141 * @param commonPartName
1142 * @param commonPartFileName
1146 private MultipartOutput createCollectionObjectInstanceFromRawXml(String testName, String commonPartName,
1147 String commonPartFileName) throws Exception {
1149 MultipartOutput multipart = new MultipartOutput();
1150 String stringObject = getXmlDocumentAsString(commonPartFileName);
1151 if (logger.isDebugEnabled()) {
1152 logger.debug(testName + " to be created, collectionobject common " + "\n" + stringObject);
1154 OutputPart commonPart = multipart.addPart(stringObject,
1155 MediaType.APPLICATION_XML_TYPE);
1156 commonPart.getHeaders().add("label", commonPartName);
1163 * Gets the nH part name.
1165 * @return the nH part name
1167 private String getNHPartName() {
1168 return "collectionobjects_naturalhistory";
1172 * Creates the from xml file.
1174 * @param testName the test name
1175 * @param fileName the file name
1176 * @param useJaxb the use jaxb
1177 * @return the string
1178 * @throws Exception the exception
1180 private String createFromXmlFile(String testName, String fileName, boolean useJaxb) throws Exception {
1181 // Perform setup, such as initializing the type of service request
1182 // (e.g. CREATE, DELETE), its valid and expected status codes, and
1183 // its associated HTTP method name (e.g. POST, DELETE).
1184 setupCreate(testName);
1186 MultipartOutput multipart = null;
1188 CollectionObjectClient client = new CollectionObjectClient();
1190 multipart = createCollectionObjectInstanceFromXml(testName,
1191 client.getCommonPartName(), fileName);
1193 multipart = createCollectionObjectInstanceFromRawXml(testName,
1194 client.getCommonPartName(), fileName);
1196 ClientResponse<Response> res = client.create(multipart);
1197 int statusCode = res.getStatus();
1199 if (logger.isDebugEnabled()) {
1200 logger.debug(testName + ": status = " + statusCode);
1202 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
1203 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
1204 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
1205 String newId = extractId(res);
1206 allResourceIdsCreated.add(newId);