2 * This document is a part of the source code and related artifacts
3 * for CollectionSpace, an open source collections management system
4 * for museums and related institutions:
6 * http://www.collectionspace.org
7 * http://wiki.collectionspace.org
9 * Copyright © 2009 Regents of the University of California
11 * Licensed under the Educational Community License (ECL), Version 2.0.
12 * You may not use this file except in compliance with this License.
14 * You may obtain a copy of the ECL 2.0 License at
15 * https://source.collectionspace.org/collection-space/LICENSE.txt
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
23 package org.collectionspace.services.client.test;
25 import java.util.ArrayList;
26 import java.util.List;
27 import javax.ws.rs.core.MediaType;
28 import javax.ws.rs.core.Response;
30 import org.collectionspace.services.client.CollectionObjectClient;
31 import org.collectionspace.services.collectionobject.CollectionobjectsCommon;
32 import org.collectionspace.services.collectionobject.domain.naturalhistory.CollectionobjectsNaturalhistory;
33 import org.collectionspace.services.collectionobject.CollectionobjectsCommonList;
34 import org.collectionspace.services.collectionobject.ResponsibleDepartmentList;
35 import org.jboss.resteasy.client.ClientResponse;
37 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
38 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
39 import org.jboss.resteasy.plugins.providers.multipart.OutputPart;
40 import org.testng.Assert;
41 import org.testng.annotations.AfterClass;
42 import org.testng.annotations.Test;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
48 * CollectionObjectServiceTest, carries out tests against a
49 * deployed and running CollectionObject Service.
51 * $LastChangedRevision$
54 public class CollectionObjectServiceTest extends AbstractServiceTestImpl {
56 private final Logger logger =
57 LoggerFactory.getLogger(CollectionObjectServiceTest.class);
58 // Instance variables specific to this test.
59 private CollectionObjectClient client = new CollectionObjectClient();
60 private String knownResourceId = null;
61 private List<String> allResourceIdsCreated = new ArrayList();
62 private boolean multivalue; //toggle
65 * This method is called only by the parent class, AbstractServiceTest
68 protected String getServicePathComponent() {
69 return client.getServicePathComponent();
72 // ---------------------------------------------------------------
73 // CRUD tests : CREATE tests
74 // ---------------------------------------------------------------
77 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
78 public void create(String testName) throws Exception {
80 // Perform setup, such as initializing the type of service request
81 // (e.g. CREATE, DELETE), its valid and expected status codes, and
82 // its associated HTTP method name (e.g. POST, DELETE).
83 setupCreate(testName);
85 // Submit the request to the service and store the response.
86 String identifier = createIdentifier();
87 MultipartOutput multipart =
88 createCollectionObjectInstance(client.getCommonPartName(), identifier);
89 ClientResponse<Response> res = client.create(multipart);
90 int statusCode = res.getStatus();
92 // Check the status code of the response: does it match
93 // the expected response(s)?
96 // Does it fall within the set of valid status codes?
97 // Does it exactly match the expected status code?
98 if (logger.isDebugEnabled()) {
99 logger.debug(testName + ": status = " + statusCode);
101 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
102 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
103 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
105 // Store the ID returned from the first resource created
106 // for additional tests below.
107 if (knownResourceId == null) {
108 knownResourceId = extractId(res);
109 if (logger.isDebugEnabled()) {
110 logger.debug(testName + ": knownResourceId=" + knownResourceId);
114 // Store the IDs from every resource created by tests,
115 // so they can be deleted after tests have been run.
116 allResourceIdsCreated.add(extractId(res));
121 * Tests to diagnose and verify the fixed status of CSPACE-1026,
122 * "Whitespace at certain points in payload cause failure"
124 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
125 dependsOnMethods = {"create", "testSubmitRequest"})
126 public void createFromXmlCambridge(String testName) throws Exception {
128 createFromXmlFile(testName, "./test-data/testCambridge.xml", true);
129 testSubmitRequest(newId);
132 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
133 dependsOnMethods = {"create", "testSubmitRequest"})
134 public void createFromXmlRFWS1(String testName) throws Exception {
136 createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp1.xml", false);
137 testSubmitRequest(newId);
140 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
141 dependsOnMethods = {"create", "testSubmitRequest"})
142 public void createFromXmlRFWS2(String testName) throws Exception {
144 createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp2.xml", false);
145 testSubmitRequest(newId);
148 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
149 dependsOnMethods = {"create", "testSubmitRequest"})
150 public void createFromXmlRFWS3(String testName) throws Exception {
152 createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp3.xml", false);
153 testSubmitRequest(newId);
156 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
157 dependsOnMethods = {"create", "testSubmitRequest"})
158 public void createFromXmlRFWS4(String testName) throws Exception {
160 createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp4.xml", false);
161 testSubmitRequest(newId);
165 * Tests to diagnose and verify the fixed status of CSPACE-1248,
166 * "Wedged records created!" (i.e. records with child repeatable
167 * fields, which contain null values, can be successfully created
168 * but an error occurs on trying to retrieve those records).
170 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
171 dependsOnMethods = {"create", "testSubmitRequest"})
172 public void createWithNullValueRepeatableField(String testName) throws Exception {
174 createFromXmlFile(testName, "./target/test-classes/test-data/repfield_null1.xml", false);
175 if (logger.isDebugEnabled()) {
176 logger.debug("Successfully created record with null value repeatable field.");
177 logger.debug("Attempting to retrieve just-created record ...");
179 testSubmitRequest(newId);
183 * @see org.collectionspace.services.client.test.ServiceTest#createList()
186 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
187 dependsOnMethods = {"create"})
188 public void createList(String testName) throws Exception {
189 for (int i = 0; i < 3; i++) {
195 // Placeholders until the three tests below can be uncommented.
196 // See Issue CSPACE-401.
198 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
199 public void createWithEmptyEntityBody(String testName) throws Exception {
203 * Test how the service handles XML that is not well formed,
204 * when sent in the payload of a Create request.
206 * @param testName The name of this test method. This name is supplied
207 * automatically, via reflection, by a TestNG 'data provider' in
211 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
212 public void createWithMalformedXml(String testName) throws Exception {
213 setupCreate(testName);
215 CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
216 collectionObject.setTitle("atitle");
217 //don't set objectNumber to check validation
218 collectionObject.setObjectName("some name");
219 MultipartOutput multipart =
220 createCollectionObjectInstance(client.getCommonPartName(), collectionObject, null);
221 ClientResponse<Response> res = client.create(multipart);
222 int statusCode = res.getStatus();
224 if (logger.isDebugEnabled()) {
225 logger.debug(testName + ": status = " + statusCode);
227 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
228 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
229 Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
233 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
234 public void createWithWrongXmlSchema(String testName) throws Exception {
240 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
241 dependsOnMethods = {"create", "testSubmitRequest"})
242 public void createWithEmptyEntityBody(String testName) throwsException {
245 setupCreateWithEmptyEntityBody(testName);
247 // Submit the request to the service and store the response.
248 String method = REQUEST_TYPE.httpMethodName();
249 String url = getServiceRootURL();
250 String mediaType = MediaType.APPLICATION_XML;
251 final String entity = "";
252 int statusCode = submitRequest(method, url, mediaType, entity);
254 // Check the status code of the response: does it match
255 // the expected response(s)?
256 if(logger.isDebugEnabled()){
257 logger.debug(testName + ": url=" + url +
258 " status=" + statusCode);
260 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
261 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
262 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
266 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
267 dependsOnMethods = {"create", "testSubmitRequest"})
268 public void createWithMalformedXml(String testName) throws Exception {
271 setupCreateWithMalformedXml(testName);
273 // Submit the request to the service and store the response.
274 String method = REQUEST_TYPE.httpMethodName();
275 String url = getServiceRootURL();
276 String mediaType = MediaType.APPLICATION_XML;
277 final String entity = MALFORMED_XML_DATA; // Constant from base class.
278 int statusCode = submitRequest(method, url, mediaType, entity);
280 // Check the status code of the response: does it match
281 // the expected response(s)?
282 if(logger.isDebugEnabled()){
283 logger.debug(testName + ": url=" + url +
284 " status=" + statusCode);
286 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
287 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
288 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
292 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
293 dependsOnMethods = {"create", "testSubmitRequest"})
294 public void createWithWrongXmlSchema(String testName) throws Exception {
297 setupCreateWithWrongXmlSchema(testName);
299 // Submit the request to the service and store the response.
300 String method = REQUEST_TYPE.httpMethodName();
301 String url = getServiceRootURL();
302 String mediaType = MediaType.APPLICATION_XML;
303 final String entity = WRONG_XML_SCHEMA_DATA;
304 int statusCode = submitRequest(method, url, mediaType, entity);
306 // Check the status code of the response: does it match
307 // the expected response(s)?
308 if(logger.isDebugEnabled()){
309 logger.debug(testName + ": url=" + url +
310 " status=" + statusCode);
312 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
313 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
314 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
319 * Test how the service handles, in a Create request, payloads
320 * containing null values (or, in the case of String fields,
321 * empty String values) in one or more fields which must be
322 * present and are required to contain non-empty values.
324 * This is a test of code and/or configuration in the service's
325 * validation routine(s).
327 * @param testName The name of this test method. This name is supplied
328 * automatically, via reflection, by a TestNG 'data provider' in
331 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
332 public void createWithRequiredValuesNullOrEmpty(String testName) throws Exception {
333 setupCreate(testName);
335 // Build a payload with invalid content, by omitting a
336 // field (objectNumber) which must be present, and in which
337 // a non-empty value is required, as enforced by the service's
338 // validation routine(s).
339 CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
340 collectionObject.setTitle("atitle");
341 collectionObject.setObjectName("some name");
343 // Submit the request to the service and store the response.
344 MultipartOutput multipart =
345 createCollectionObjectInstance(client.getCommonPartName(), collectionObject, null);
346 ClientResponse<Response> res = client.create(multipart);
347 int statusCode = res.getStatus();
349 // Read the response and verify that the create attempt failed.
350 if (logger.isDebugEnabled()) {
351 logger.debug(testName + ": status = " + statusCode);
353 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
354 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
355 Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
357 // FIXME: Consider splitting off the following into its own test method.
359 // Build a payload with invalid content, by setting a value to the
360 // empty String, in a field that requires a non-empty value,
361 // as enforced by the service's validation routine(s).
362 collectionObject = new CollectionobjectsCommon();
363 collectionObject.setTitle("atitle");
364 collectionObject.setObjectName("some name");
365 collectionObject.setObjectNumber("");
367 // Submit the request to the service and store the response.
369 createCollectionObjectInstance(client.getCommonPartName(), collectionObject, null);
370 res = client.create(multipart);
371 statusCode = res.getStatus();
373 // Read the response and verify that the create attempt failed.
374 if (logger.isDebugEnabled()) {
375 logger.debug(testName + ": status = " + statusCode);
377 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
378 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
379 Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
384 // ---------------------------------------------------------------
385 // CRUD tests : READ tests
386 // ---------------------------------------------------------------
389 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
390 dependsOnMethods = {"create"})
391 public void read(String testName) throws Exception {
396 // Submit the request to the service and store the response.
397 ClientResponse<MultipartInput> res = client.read(knownResourceId);
398 int statusCode = res.getStatus();
400 // Check the status code of the response: does it match
401 // the expected response(s)?
402 if (logger.isDebugEnabled()) {
403 logger.debug(testName + ": status = " + statusCode);
405 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
406 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
407 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
409 MultipartInput input = (MultipartInput) res.getEntity();
411 if (logger.isDebugEnabled()) {
412 logger.debug(testName + ": Reading Common part ...");
414 CollectionobjectsCommon collectionObject =
415 (CollectionobjectsCommon) extractPart(input,
416 client.getCommonPartName(), CollectionobjectsCommon.class);
417 Assert.assertNotNull(collectionObject);
419 if (logger.isDebugEnabled()) {
420 logger.debug(testName + ": Reading Natural History part ...");
422 CollectionobjectsNaturalhistory conh =
423 (CollectionobjectsNaturalhistory) extractPart(input,
424 getNHPartName(), CollectionobjectsNaturalhistory.class);
425 Assert.assertNotNull(conh);
430 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
431 dependsOnMethods = {"read"})
432 public void readNonExistent(String testName) throws Exception {
435 setupReadNonExistent(testName);
437 // Submit the request to the service and store the response.
438 ClientResponse<MultipartInput> res = client.read(NON_EXISTENT_ID);
439 int statusCode = res.getStatus();
441 // Check the status code of the response: does it match
442 // the expected response(s)?
443 if (logger.isDebugEnabled()) {
444 logger.debug(testName + ": status = " + statusCode);
446 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
447 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
448 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
451 // ---------------------------------------------------------------
452 // CRUD tests : READ_LIST tests
453 // ---------------------------------------------------------------
456 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
457 dependsOnMethods = {"createList", "read"})
458 public void readList(String testName) throws Exception {
461 setupReadList(testName);
463 // Submit the request to the service and store the response.
464 ClientResponse<CollectionobjectsCommonList> res = client.readList();
465 CollectionobjectsCommonList list = res.getEntity();
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 // Optionally output additional data about list members for debugging.
478 boolean iterateThroughList = false;
479 if (iterateThroughList && logger.isDebugEnabled()) {
480 List<CollectionobjectsCommonList.CollectionObjectListItem> items =
481 list.getCollectionObjectListItem();
484 for (CollectionobjectsCommonList.CollectionObjectListItem item : items) {
485 logger.debug(testName + ": list-item[" + i + "] csid="
487 logger.debug(testName + ": list-item[" + i + "] objectNumber="
488 + item.getObjectNumber());
489 logger.debug(testName + ": list-item[" + i + "] URI="
499 // ---------------------------------------------------------------
500 // CRUD tests : UPDATE tests
501 // ---------------------------------------------------------------
504 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
505 dependsOnMethods = {"read"})
506 public void update(String testName) throws Exception {
509 setupUpdate(testName);
511 // Read an existing resource that will be updated.
512 ClientResponse<MultipartInput> res = updateRetrieve(testName, knownResourceId);
514 // Extract its common part.
515 MultipartInput input = (MultipartInput) res.getEntity();
516 CollectionobjectsCommon collectionObject =
517 (CollectionobjectsCommon) extractPart(input,
518 client.getCommonPartName(), CollectionobjectsCommon.class);
519 Assert.assertNotNull(collectionObject);
521 // Change the content of one or more fields in the common part.
522 collectionObject.setObjectNumber("updated-" + collectionObject.getObjectNumber());
523 collectionObject.setObjectName("updated-" + collectionObject.getObjectName());
524 if (logger.isDebugEnabled()) {
525 logger.debug("sparse update that will be sent in update request:");
526 logger.debug(objectAsXmlString(collectionObject,
527 CollectionobjectsCommon.class));
530 // Send the changed resource to be updated.
531 res = updateSend(testName, knownResourceId, collectionObject);
532 int statusCode = res.getStatus();
533 // Check the status code of the response: does it match the expected response(s)?
534 if (logger.isDebugEnabled()) {
535 logger.debug(testName + ": status = " + statusCode);
537 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
538 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
539 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
541 // Read the response and verify that the resource was correctly updated.
542 input = (MultipartInput) res.getEntity();
543 CollectionobjectsCommon updatedCollectionObject =
544 (CollectionobjectsCommon) extractPart(input,
545 client.getCommonPartName(), CollectionobjectsCommon.class);
546 Assert.assertNotNull(updatedCollectionObject);
547 Assert.assertEquals(updatedCollectionObject.getObjectName(),
548 collectionObject.getObjectName(),
549 "Data in updated object did not match submitted data.");
553 private ClientResponse<MultipartInput> updateRetrieve(String testName, String id) {
554 final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
555 ClientResponse<MultipartInput> res = client.read(id);
556 if (logger.isDebugEnabled()) {
557 logger.debug("read in updateRetrieve for " + testName + " status = " + res.getStatus());
559 Assert.assertEquals(res.getStatus(), EXPECTED_STATUS);
560 if (logger.isDebugEnabled()) {
561 logger.debug("got object to updateRetrieve for " + testName + " with ID: " + id);
566 private ClientResponse<MultipartInput> updateSend(String testName, String id,
567 CollectionobjectsCommon collectionObject) {
568 MultipartOutput output = new MultipartOutput();
569 OutputPart commonPart = output.addPart(collectionObject, MediaType.APPLICATION_XML_TYPE);
570 commonPart.getHeaders().add("label", client.getCommonPartName());
571 ClientResponse<MultipartInput> res = client.update(knownResourceId, output);
576 // Placeholders until the three tests below can be uncommented.
577 // See Issue CSPACE-401.
579 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
580 dependsOnMethods = {"read"})
581 public void updateWithEmptyEntityBody(String testName) throws Exception {
585 * Test how the service handles XML that is not well formed,
586 * when sent in the payload of an Update request.
588 * @param testName The name of this test method. This name is supplied
589 * automatically, via reflection, by a TestNG 'data provider' in
593 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
594 dependsOnMethods = {"read"})
595 public void updateWithMalformedXml(String testName) throws Exception {
597 setupUpdate(testName);
598 if (logger.isDebugEnabled()) {
599 logger.debug(testName + " got object to update with ID: " + knownResourceId);
602 // Read an existing record for updating
603 ClientResponse<MultipartInput> res = updateRetrieve(testName, knownResourceId);
605 MultipartInput input = (MultipartInput) res.getEntity();
606 CollectionobjectsCommon collectionObject =
607 (CollectionobjectsCommon) extractPart(input,
608 client.getCommonPartName(), CollectionobjectsCommon.class);
609 Assert.assertNotNull(collectionObject);
611 //update with invalid content
612 collectionObject.setObjectNumber("");
614 if (logger.isDebugEnabled()) {
615 logger.debug(testName + " updated object");
616 logger.debug(objectAsXmlString(collectionObject,
617 CollectionobjectsCommon.class));
620 // Submit the request to the service and store the response.
621 res = updateSend(testName, knownResourceId, collectionObject);
622 int statusCode = res.getStatus();
623 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
624 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
625 Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
630 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
631 dependsOnMethods = {"read"})
632 public void updateWithWrongXmlSchema(String testName) throws Exception {
637 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
638 dependsOnMethods = {"create", "update", "testSubmitRequest"})
639 public void updateWithEmptyEntityBody(String testName) throws Exception {
642 setupUpdateWithEmptyEntityBody(testName);
644 // Submit the request to the service and store the response.
645 String method = REQUEST_TYPE.httpMethodName();
646 String url = getResourceURL(knownResourceId);
647 String mediaType = MediaType.APPLICATION_XML;
648 final String entity = "";
649 int statusCode = submitRequest(method, url, mediaType, entity);
651 // Check the status code of the response: does it match
652 // the expected response(s)?
653 if(logger.isDebugEnabled()){
654 logger.debug(testName + ": url=" + url +
655 " status=" + statusCode);
657 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
658 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
659 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
663 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
664 dependsOnMethods = {"create", "update", "testSubmitRequest"})
665 public void updateWithMalformedXml() throws Exception {
668 setupUpdateWithMalformedXml(testName);
670 // Submit the request to the service and store the response.
671 String method = REQUEST_TYPE.httpMethodName();
672 String url = getResourceURL(knownResourceId);
673 final String entity = MALFORMED_XML_DATA;
674 String mediaType = MediaType.APPLICATION_XML;
675 int statusCode = submitRequest(method, url, mediaType, entity);
677 // Check the status code of the response: does it match
678 // the expected response(s)?
679 if(logger.isDebugEnabled()){
680 logger.debug(testName + ": url=" + url +
681 " status=" + statusCode);
683 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
684 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
685 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
689 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
690 dependsOnMethods = {"create", "update", "testSubmitRequest"})
691 public void updateWithWrongXmlSchema(String testName) throws Exception {
694 setupUpdateWithWrongXmlSchema(String testName);
696 // Submit the request to the service and store the response.
697 String method = REQUEST_TYPE.httpMethodName();
698 String url = getResourceURL(knownResourceId);
699 String mediaType = MediaType.APPLICATION_XML;
700 final String entity = WRONG_XML_SCHEMA_DATA;
701 int statusCode = submitRequest(method, url, mediaType, entity);
703 // Check the status code of the response: does it match
704 // the expected response(s)?
705 if(logger.isDebugEnabled()){
706 logger.debug(testName + ": url=" + url +
707 " status=" + statusCode);
709 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
710 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
711 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
716 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
717 dependsOnMethods = {"update", "testSubmitRequest"})
718 public void updateNonExistent(String testName) throws Exception {
721 setupUpdateNonExistent(testName);
723 // Submit the request to the service and store the response.
725 // Note: The ID used in this 'create' call may be arbitrary.
726 // The only relevant ID may be the one used in updateCollectionObject(), below.
727 MultipartOutput multipart =
728 createCollectionObjectInstance(client.getCommonPartName(),
730 ClientResponse<MultipartInput> res =
731 client.update(NON_EXISTENT_ID, multipart);
732 int statusCode = res.getStatus();
734 // Check the status code of the response: does it match
735 // the expected response(s)?
736 if (logger.isDebugEnabled()) {
737 logger.debug(testName + ": status = " + statusCode);
739 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
740 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
741 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
745 * Test how the service handles, in an Update request, payloads
746 * containing null values (or, in the case of String fields,
747 * empty String values) in one or more fields in which non-empty
748 * values are required.
750 * This is a test of code and/or configuration in the service's
751 * validation routine(s).
753 * @param testName The name of this test method. This name is supplied
754 * automatically, via reflection, by a TestNG 'data provider' in
757 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
758 dependsOnMethods = {"read"})
759 public void updateWithRequiredValuesNullOrEmpty(String testName) throws Exception {
761 setupUpdate(testName);
762 if (logger.isDebugEnabled()) {
763 logger.debug(testName + " got object to update with ID: " + knownResourceId);
766 // Read an existing record for updating.
767 ClientResponse<MultipartInput> res = updateRetrieve(testName, knownResourceId);
769 MultipartInput input = (MultipartInput) res.getEntity();
770 CollectionobjectsCommon collectionObject =
771 (CollectionobjectsCommon) extractPart(input,
772 client.getCommonPartName(), CollectionobjectsCommon.class);
773 Assert.assertNotNull(collectionObject);
775 // Update with invalid content, by setting a value to the
776 // empty String, in a field that requires a non-empty value,
777 // as enforced by the service's validation routine(s).
778 collectionObject.setObjectNumber("");
780 if (logger.isDebugEnabled()) {
781 logger.debug(testName + " updated object");
782 logger.debug(objectAsXmlString(collectionObject,
783 CollectionobjectsCommon.class));
786 // Submit the request to the service and store the response.
787 res = updateSend(testName, knownResourceId, collectionObject);
788 int statusCode = res.getStatus();
790 // Read the response and verify that the update attempt failed.
791 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
792 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
793 Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
797 // ---------------------------------------------------------------
798 // CRUD tests : DELETE tests
799 // ---------------------------------------------------------------
802 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
803 dependsOnMethods = {"create", "readList", "testSubmitRequest", "update"})
804 public void delete(String testName) throws Exception {
807 setupDelete(testName);
809 // Submit the request to the service and store the response.
810 ClientResponse<Response> res = client.delete(knownResourceId);
811 int statusCode = res.getStatus();
813 // Check the status code of the response: does it match
814 // the expected response(s)?
815 if (logger.isDebugEnabled()) {
816 logger.debug(testName + ": status = " + statusCode);
818 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
819 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
820 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
825 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
826 dependsOnMethods = {"delete"})
827 public void deleteNonExistent(String testName) throws Exception {
830 setupDeleteNonExistent(testName);
832 // Submit the request to the service and store the response.
833 ClientResponse<Response> res = client.delete(NON_EXISTENT_ID);
834 int statusCode = res.getStatus();
836 // Check the status code of the response: does it match
837 // the expected response(s)?
838 if (logger.isDebugEnabled()) {
839 logger.debug(testName + ": status = " + statusCode);
841 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
842 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
843 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
846 // ---------------------------------------------------------------
847 // Utility tests : tests of code used in tests above
848 // ---------------------------------------------------------------
850 * Tests the code for manually submitting data that is used by several
851 * of the methods above.
854 @Test(dependsOnMethods = {"create", "read"})
855 public void testSubmitRequest() throws Exception {
856 testSubmitRequest(knownResourceId);
859 private void testSubmitRequest(String resourceId) throws Exception {
861 // Expected status code: 200 OK
862 final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
864 // Submit the request to the service and store the response.
865 String method = ServiceRequestType.READ.httpMethodName();
866 String url = getResourceURL(resourceId);
867 int statusCode = submitRequest(method, url);
869 // Check the status code of the response: does it match
870 // the expected response(s)?
871 if (logger.isDebugEnabled()) {
872 logger.debug("testSubmitRequest: url=" + url
873 + " status=" + statusCode);
875 Assert.assertEquals(statusCode, EXPECTED_STATUS);
879 // ---------------------------------------------------------------
880 // Cleanup of resources created during testing
881 // ---------------------------------------------------------------
883 * Deletes all resources created by tests, after all tests have been run.
885 * This cleanup method will always be run, even if one or more tests fail.
886 * For this reason, it attempts to remove all resources created
887 * at any point during testing, even if some of those resources
888 * may be expected to be deleted by certain tests.
890 @AfterClass(alwaysRun = true)
891 public void cleanUp() {
892 if (logger.isDebugEnabled()) {
893 logger.debug("Cleaning up temporary resources created for testing ...");
895 for (String resourceId : allResourceIdsCreated) {
896 // Note: Any non-success responses are ignored and not reported.
897 ClientResponse<Response> res = client.delete(resourceId);
901 // ---------------------------------------------------------------
902 // Utility methods used by tests above
903 // ---------------------------------------------------------------
904 private MultipartOutput createCollectionObjectInstance(String commonPartName,
906 return createCollectionObjectInstance(commonPartName,
907 "objectNumber-" + identifier,
908 "objectName-" + identifier);
911 private MultipartOutput createCollectionObjectInstance(String commonPartName,
912 String objectNumber, String objectName) {
913 CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
914 ResponsibleDepartmentList deptList = new ResponsibleDepartmentList();
915 List<String> depts = deptList.getResponsibleDepartment();
916 // @TODO Use properly formatted refNames for representative departments
917 // in this example test record. The following are mere placeholders.
918 depts.add("urn:org.collectionspace.services.department:Registrar");
920 depts.add("urn:org.walkerart.department:Fine Art");
922 multivalue = !multivalue;
923 //FIXME: Title does not need to be set.
924 collectionObject.setTitle("atitle");
925 collectionObject.setResponsibleDepartments(deptList);
926 collectionObject.setObjectNumber(objectNumber);
927 collectionObject.setOtherNumber("urn:org.walkerart.id:123");
928 collectionObject.setObjectName(objectName);
929 collectionObject.setAge(""); //test for null string
930 collectionObject.setBriefDescription("Papier mache bird cow mask with horns, "
931 + "painted red with black and yellow spots. "
932 + "Puerto Rico. ca. 8" high, 6" wide, projects 10" (with horns).");
934 CollectionobjectsNaturalhistory conh = new CollectionobjectsNaturalhistory();
935 conh.setNhString("test-string");
937 conh.setNhLong(9999);
940 MultipartOutput multipart = createCollectionObjectInstance(commonPartName, collectionObject, conh);
944 private MultipartOutput createCollectionObjectInstance(String commonPartName,
945 CollectionobjectsCommon collectionObject, CollectionobjectsNaturalhistory conh) {
947 MultipartOutput multipart = new MultipartOutput();
948 OutputPart commonPart = multipart.addPart(collectionObject,
949 MediaType.APPLICATION_XML_TYPE);
950 commonPart.getHeaders().add("label", commonPartName);
952 if (logger.isDebugEnabled()) {
953 logger.debug("to be created, collectionobject common");
954 logger.debug(objectAsXmlString(collectionObject,
955 CollectionobjectsCommon.class));
959 OutputPart nhPart = multipart.addPart(conh, MediaType.APPLICATION_XML_TYPE);
960 nhPart.getHeaders().add("label", getNHPartName());
962 if (logger.isDebugEnabled()) {
963 logger.debug("to be created, collectionobject nhistory");
964 logger.debug(objectAsXmlString(conh,
965 CollectionobjectsNaturalhistory.class));
973 * createCollectionObjectInstanceFromXml uses JAXB unmarshaller to retrieve
974 * collectionobject from given file
975 * @param commonPartName
976 * @param commonPartFileName
980 private MultipartOutput createCollectionObjectInstanceFromXml(String testName, String commonPartName,
981 String commonPartFileName) throws Exception {
983 CollectionobjectsCommon collectionObject =
984 (CollectionobjectsCommon) getObjectFromFile(CollectionobjectsCommon.class,
986 MultipartOutput multipart = new MultipartOutput();
987 OutputPart commonPart = multipart.addPart(collectionObject,
988 MediaType.APPLICATION_XML_TYPE);
989 commonPart.getHeaders().add("label", commonPartName);
991 if (logger.isDebugEnabled()) {
992 logger.debug(testName + " to be created, collectionobject common");
993 logger.debug(objectAsXmlString(collectionObject,
994 CollectionobjectsCommon.class));
1001 * createCollectionObjectInstanceFromRawXml uses stringified collectionobject
1002 * retrieve from given file
1003 * @param commonPartName
1004 * @param commonPartFileName
1008 private MultipartOutput createCollectionObjectInstanceFromRawXml(String testName, String commonPartName,
1009 String commonPartFileName) throws Exception {
1011 MultipartOutput multipart = new MultipartOutput();
1012 String stringObject = getXmlDocumentAsString(commonPartFileName);
1013 if (logger.isDebugEnabled()) {
1014 logger.debug(testName + " to be created, collectionobject common " + "\n" + stringObject);
1016 OutputPart commonPart = multipart.addPart(stringObject,
1017 MediaType.APPLICATION_XML_TYPE);
1018 commonPart.getHeaders().add("label", commonPartName);
1024 private String getNHPartName() {
1025 return "collectionobjects_naturalhistory";
1028 private String createFromXmlFile(String testName, String fileName, boolean useJaxb) throws Exception {
1029 // Perform setup, such as initializing the type of service request
1030 // (e.g. CREATE, DELETE), its valid and expected status codes, and
1031 // its associated HTTP method name (e.g. POST, DELETE).
1032 setupCreate(testName);
1034 MultipartOutput multipart = null;
1037 multipart = createCollectionObjectInstanceFromXml(testName,
1038 client.getCommonPartName(), fileName);
1040 multipart = createCollectionObjectInstanceFromRawXml(testName,
1041 client.getCommonPartName(), fileName);
1043 ClientResponse<Response> res = client.create(multipart);
1044 int statusCode = res.getStatus();
1046 if (logger.isDebugEnabled()) {
1047 logger.debug(testName + ": status = " + statusCode);
1049 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
1050 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
1051 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
1052 String newId = extractId(res);
1053 allResourceIdsCreated.add(newId);