@Test
public void testHandleRequest() throws Exception {

  final String BODY_STRING = "Body string";
  Request request = createNiceMock(Request.class);
  RequestBody body = createNiceMock(RequestBody.class);
  ResourceInstance resourceInstance = createNiceMock(ResourceInstance.class);
  ResourceDefinition resourceDefinition = createNiceMock(ResourceDefinition.class);
  ResourceInstanceFactory resourceInstanceFactory = createNiceMock(ResourceInstanceFactory.class);
  Query query = createNiceMock(Query.class);
  Predicate predicate = createNiceMock(Predicate.class);
  Result result = createNiceMock(Result.class);
  ResourceInstance subResource = createNiceMock(ResourceInstance.class);
  ResourceDefinition subResourceDefinition = createNiceMock(ResourceDefinition.class);
  ClusterController controller = createNiceMock(ClusterController.class);
  Schema serviceSchema = createNiceMock(Schema.class);
  Schema componentSchema = createNiceMock(Schema.class);
  String resourceKeyProperty = "resourceKeyProperty";
  String createKeyProperty = "createKeyProperty";
  Resource resource1 = createNiceMock(Resource.class);
  Resource resource2 = createNiceMock(Resource.class);
  PersistenceManager pm = createNiceMock(PersistenceManager.class);
  ResourceInstance createResource = createNiceMock(ResourceInstance.class);
  RequestStatus status = createNiceMock(RequestStatus.class);
  Resource statusResource1 = createNiceMock(Resource.class);
  Resource statusResource2 = createNiceMock(Resource.class);
  RequestHandler readHandler = createStrictMock(RequestHandler.class);
  ResultStatus resultStatus = createNiceMock(ResultStatus.class);
  Capture<RequestBody> bodyCapture = EasyMock.newCapture();
  //  test request body
  //    {
  //      "components" : [
  //        { "ServiceComponentInfo" : {
  //            "component_name" : "SECONDARY_NAMENODE"
  //          }
  //        },
  //        { "ServiceComponentInfo" : {
  //            "component_name" : "HDFS_CLIENT"
  //          }
  //        }
  //      ]
  //   }
  Map<Resource.Type, String> mapIds = new HashMap<Resource.Type, String>();
  Set<NamedPropertySet> setRequestProps = new HashSet<NamedPropertySet>();
  Map<String, Object> mapProperties = new HashMap<String, Object>();
  Set<Map<String, Object>> arraySet  = new HashSet<Map<String, Object>>();
  mapProperties.put("components", arraySet);
  Map<String, Object> map = new HashMap<String, Object>();
  map.put(PropertyHelper.getPropertyId("ServiceComponentInfo", "component_name"), "SECONDARY_NAMENODE");
  arraySet.add(map);
  map = new HashMap<String, Object>();
  map.put(PropertyHelper.getPropertyId("ServiceComponentInfo", "component_name"), "HDFS_CLIENT");
  arraySet.add(map);
  setRequestProps.add(new NamedPropertySet("", mapProperties));
  Set<Map<String, Object>> setCreateProps = new HashSet<Map<String, Object>>();
  Map<String, Object> map1 = new HashMap<String, Object>();
  map1.put(PropertyHelper.getPropertyId("ServiceComponentInfo", "component_name"), "SECONDARY_NAMENODE");
  map1.put(createKeyProperty, "id1");
  setCreateProps.add(map1);
  Map<String, Object> map2 = new HashMap<String, Object>();
  map2.put(PropertyHelper.getPropertyId("ServiceComponentInfo", "component_name"), "SECONDARY_NAMENODE");
  map2.put(createKeyProperty, "id2");
  setCreateProps.add(map2);
  Map<String, Object> map3 = new HashMap<String, Object>();
  map3.put(PropertyHelper.getPropertyId("ServiceComponentInfo", "component_name"), "HDFS_CLIENT");
  map3.put(createKeyProperty, "id1");
  setCreateProps.add(map3);
  Map<String, Object> map4 = new HashMap<String, Object>();
  map4.put(PropertyHelper.getPropertyId("ServiceComponentInfo", "component_name"), "HDFS_CLIENT");
  map4.put(createKeyProperty, "id2");
  setCreateProps.add(map4);
  Map<String, ResourceInstance> mapSubResources = new HashMap<String, ResourceInstance>();
  mapSubResources.put("components", subResource);
  TreeNode<Resource> resultTree = new TreeNodeImpl<Resource>(null, null, "result");
  resultTree.addChild(resource1, "resource1");
  resultTree.addChild(resource2, "resource2");
  Set<Resource> setStatusResources = new HashSet<Resource>();
  setStatusResources.add(statusResource1);
  setStatusResources.add(statusResource2);
  //expectations
  expect(readHandler.handleRequest(request)).andReturn(result);
  expect(result.getStatus()).andReturn(resultStatus).anyTimes();
  expect(resultStatus.isErrorState()).andReturn(false);
  expect(result.getResultTree()).andReturn(resultTree);
  expect(body.getBody()).andReturn(BODY_STRING).anyTimes();
  
  expect(request.getResource()).andReturn(resourceInstance).anyTimes();
  expect(request.getBody()).andReturn(body).anyTimes();
  expect(body.getNamedPropertySets()).andReturn(setRequestProps).anyTimes();
  expect(resourceInstance.getResourceDefinition()).andReturn(resourceDefinition).anyTimes();
  expect(resourceInstance.getKeyValueMap()).andReturn(mapIds).anyTimes();
  expect(resourceInstance.getSubResources()).andReturn(mapSubResources).anyTimes();
  expect(resourceDefinition.getType()).andReturn(Resource.Type.Service).anyTimes();
  expect(resourceDefinition.isCreatable()).andReturn(true).anyTimes();
  expect(subResource.getResourceDefinition()).andReturn(subResourceDefinition).anyTimes();
  expect(subResourceDefinition.getType()).andReturn(Resource.Type.Component).anyTimes();
  expect(controller.getSchema(Resource.Type.Service)).andReturn(serviceSchema).anyTimes();
  expect(controller.getSchema(Resource.Type.Component)).andReturn(componentSchema).anyTimes();
  expect(serviceSchema.getKeyPropertyId(Resource.Type.Service)).andReturn(resourceKeyProperty).anyTimes();
  expect(componentSchema.getKeyPropertyId(Resource.Type.Service)).andReturn(createKeyProperty).anyTimes();
  expect(result.getResultTree()).andReturn(resultTree).anyTimes();
  expect(resource1.getPropertyValue(resourceKeyProperty)).andReturn("id1").anyTimes();
  expect(resource2.getPropertyValue(resourceKeyProperty)).andReturn("id2").anyTimes();
  expect(resourceInstanceFactory.createResource(Resource.Type.Component, mapIds)).
      andReturn(createResource).anyTimes();
  expect(createResource.getResourceDefinition()).andReturn(resourceDefinition).anyTimes();
  expect(pm.create(same(createResource), capture(bodyCapture))).andReturn(status);
  expect(status.getStatus()).andReturn(RequestStatus.Status.Complete).anyTimes();
  expect(status.getAssociatedResources()).andReturn(setStatusResources).anyTimes();
  expect(statusResource1.getType()).andReturn(Resource.Type.Component).anyTimes();
  expect(statusResource2.getType()).andReturn(Resource.Type.Component).anyTimes();
  replay(request, body, resourceInstance, resourceDefinition, query, predicate, result, subResource,
      subResourceDefinition, controller, serviceSchema, componentSchema, resource1, resource2,
      pm, resourceInstanceFactory, createResource, status, statusResource1, statusResource2,
      readHandler, resultStatus);
  //test
  Result testResult = new TestQueryCreateHandler(resourceInstanceFactory, controller, pm, readHandler).
      handleRequest(request);
  Collection<TreeNode<Resource>> children = testResult.getResultTree().getChild("resources").getChildren();
  assertEquals(2, children.size());
  boolean containsStatusResource1 = false;
  boolean containsStatusResource2 = false;
  for (TreeNode<Resource> child : children) {
    Resource r = child.getObject();
    if (r == statusResource1) {
      containsStatusResource1 = true;
    } else if(r == statusResource2) {
      containsStatusResource2 = true;
    }
  }
  assertTrue(containsStatusResource1);
  assertTrue(containsStatusResource2);
  assertEquals(ResultStatus.STATUS.CREATED, testResult.getStatus().getStatus());
  RequestBody createBody = bodyCapture.getValue();
  assertEquals(BODY_STRING, createBody.getBody());        
  assertEquals(4, createBody.getPropertySets().size());
  assertEquals(setCreateProps, createBody.getPropertySets());
  verify(request, body, resourceInstance, resourceDefinition, query, predicate, result, subResource,
      subResourceDefinition, controller, serviceSchema, componentSchema, resource1, resource2,
      pm, resourceInstanceFactory, createResource, status, statusResource1, statusResource2,
      readHandler, resultStatus);
}