package org.cloudfoundry.community.servicebroker.controller;
import static org.cloudfoundry.community.servicebroker.model.matchers.AsyncArgumentMatcher.anyAsyncRequest;
import static org.cloudfoundry.community.servicebroker.model.matchers.SyncArgumentMatcher.anySyncRequest;
import static org.hamcrest.Matchers.*;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.cloudfoundry.community.servicebroker.exception.*;
import org.cloudfoundry.community.servicebroker.model.*;
import org.cloudfoundry.community.servicebroker.model.fixture.ServiceFixture;
import org.cloudfoundry.community.servicebroker.model.fixture.ServiceInstanceFixture;
import org.cloudfoundry.community.servicebroker.service.*;
import org.junit.*;
import org.mockito.*;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
public class ServiceInstanceControllerIntegrationTest {
MockMvc mockMvc;
@InjectMocks
ServiceInstanceController controller;
@Mock
ServiceInstanceService serviceInstanceService;
@Mock
CatalogService catalogService;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.standaloneSetup(controller)
.setMessageConverters(new MappingJackson2HttpMessageConverter()).build();
}
@Test
public void serviceInstanceIsCreatedCorrectly() throws Exception {
ServiceInstance instance = ServiceInstanceFixture.getServiceInstance();
when(serviceInstanceService.createServiceInstance(
eq(ServiceInstanceFixture.getCreateServiceInstanceRequest())))
.thenReturn(instance);
when(catalogService.getServiceDefinition(any(String.class)))
.thenReturn(ServiceFixture.getService());
String dashboardUrl = ServiceInstanceFixture.getServiceInstance().getDashboardUrl();
String url = ServiceInstanceController.BASE_PATH + "/" + instance.getServiceInstanceId();
String body = ServiceInstanceFixture.getCreateServiceInstanceRequestJson();
mockMvc.perform(
put(url)
.contentType(MediaType.APPLICATION_JSON)
.content(body)
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isCreated())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.dashboard_url", is(dashboardUrl)));
}
@Test
public void unknownServiceDefinitionInstanceCreationFails() throws Exception {
ServiceInstance instance = ServiceInstanceFixture.getServiceInstance();
when(catalogService.getServiceDefinition(any(String.class)))
.thenReturn(null);
String url = ServiceInstanceController.BASE_PATH + "/" + instance.getServiceInstanceId();
String body = ServiceInstanceFixture.getCreateServiceInstanceRequestJson();
mockMvc.perform(
put(url)
.contentType(MediaType.APPLICATION_JSON)
.content(body)
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isUnprocessableEntity())
.andExpect(jsonPath("$.description", containsString(instance.getServiceDefinitionId())));
}
@Test
public void duplicateServiceInstanceCreationFails() throws Exception {
ServiceInstance instance = ServiceInstanceFixture.getServiceInstance();
when(catalogService.getServiceDefinition(any(String.class)))
.thenReturn(ServiceFixture.getService());
when(serviceInstanceService.createServiceInstance(any(CreateServiceInstanceRequest.class)))
.thenThrow(new ServiceInstanceExistsException(instance));
String url = ServiceInstanceController.BASE_PATH + "/" + instance.getServiceInstanceId();
String body = ServiceInstanceFixture.getCreateServiceInstanceRequestJson();
mockMvc.perform(
put(url)
.contentType(MediaType.APPLICATION_JSON)
.content(body)
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isConflict())
.andExpect(jsonPath("$.description", containsString(instance.getServiceInstanceId())));
}
@Test
public void badJsonServiceInstanceCreationFails() throws Exception {
ServiceInstance instance = ServiceInstanceFixture.getServiceInstance();
when(serviceInstanceService.createServiceInstance(any(CreateServiceInstanceRequest.class)))
.thenReturn(instance);
when(catalogService.getServiceDefinition(any(String.class)))
.thenReturn(ServiceFixture.getService());
String url = ServiceInstanceController.BASE_PATH + "/" + instance.getServiceInstanceId();
String body = ServiceInstanceFixture.getCreateServiceInstanceRequestJson();
body = body.replace("service_id", "foo");
mockMvc.perform(
put(url)
.contentType(MediaType.APPLICATION_JSON)
.content(body)
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isUnprocessableEntity())
.andExpect(jsonPath("$.description", containsString("Missing required fields")));
}
@Test
public void badJsonServiceInstanceCreationFailsMissingFields() throws Exception {
ServiceInstance instance = ServiceInstanceFixture.getServiceInstance();
when(serviceInstanceService.createServiceInstance(any(CreateServiceInstanceRequest.class)))
.thenReturn(instance);
when(catalogService.getServiceDefinition(any(String.class)))
.thenReturn(ServiceFixture.getService());
String url = ServiceInstanceController.BASE_PATH + "/" + instance.getServiceInstanceId();
String body = "{}";
mockMvc.perform(
put(url)
.contentType(MediaType.APPLICATION_JSON)
.content(body)
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isUnprocessableEntity())
.andExpect(jsonPath("$.description", containsString("serviceDefinitionId")))
.andExpect(jsonPath("$.description", containsString("planId")))
.andExpect(jsonPath("$.description", containsString("organizationGuid")))
.andExpect(jsonPath("$.description", containsString("spaceGuid")));
}
@Test
public void serviceInstanceIsDeletedSuccessfully() throws Exception {
ServiceInstance instance = ServiceInstanceFixture.getServiceInstance();
when(serviceInstanceService.deleteServiceInstance(any(DeleteServiceInstanceRequest.class)))
.thenReturn(instance);
String url = ServiceInstanceController.BASE_PATH + "/" + instance.getServiceInstanceId()
+ "?service_id=" + instance.getServiceDefinitionId()
+ "&plan_id=" + instance.getPlanId();
mockMvc.perform(delete(url)
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isOk())
//We return the service broker now, as the CC should be ignoring it.
//.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
//.andExpect(jsonPath("$", is("{}"))
;
}
@Test
public void deleteUnknownServiceInstanceFailsWithA410() throws Exception {
ServiceInstance instance = ServiceInstanceFixture.getServiceInstance();
when(serviceInstanceService.deleteServiceInstance(any(DeleteServiceInstanceRequest.class)))
.thenReturn(null);
String url = ServiceInstanceController.BASE_PATH + "/" + instance.getServiceInstanceId()
+ "?service_id=" + instance.getServiceDefinitionId()
+ "&plan_id=" + instance.getPlanId();
mockMvc.perform(delete(url)
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isGone())
.andExpect(jsonPath("$", is("{}")));
}
@Test
public void serviceInstanceIsUpdatedSuccessfully() throws Exception {
ServiceInstance instance = ServiceInstanceFixture.getServiceInstance();
when(serviceInstanceService.updateServiceInstance(
eq(ServiceInstanceFixture.getUpdateServiceInstanceRequest())))
.thenReturn(instance);
String url = ServiceInstanceController.BASE_PATH + "/" + instance.getServiceInstanceId();
String body = ServiceInstanceFixture.getUpdateServiceInstanceRequestJson();
mockMvc.perform(
patch(url).contentType(MediaType.APPLICATION_JSON).content(body)
.accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$", is("{}")));
}
@Test
public void updateUnsupportedPlanFailsWithA422() throws Exception {
ServiceInstance instance = ServiceInstanceFixture.getServiceInstance();
when(serviceInstanceService.updateServiceInstance(any(UpdateServiceInstanceRequest.class)))
.thenThrow(new ServiceInstanceUpdateNotSupportedException("description"));
String url =
ServiceInstanceController.BASE_PATH + "/" + instance.getServiceInstanceId() + "?service_id="
+ instance.getServiceDefinitionId() + "&plan_id=" + instance.getPlanId();
String body = ServiceInstanceFixture.getUpdateServiceInstanceRequestJson();
mockMvc.perform(
patch(url).contentType(MediaType.APPLICATION_JSON).content(body)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isUnprocessableEntity())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.description", containsString("description")));
}
@Test
public void createServiceAsyncRequredShoudlFailWith422() throws Exception {
ServiceInstance instance = ServiceInstanceFixture.getServiceInstance();
when(catalogService.getServiceDefinition(any(String.class)))
.thenReturn(ServiceFixture.getService());
when(serviceInstanceService.createServiceInstance(any(CreateServiceInstanceRequest.class)))
.thenThrow(new ServiceBrokerAsyncRequiredException("msg"));
String url = ServiceInstanceController.BASE_PATH + "/" + instance.getServiceInstanceId();
String body = ServiceInstanceFixture.getCreateServiceInstanceRequestJson();
mockMvc.perform(
put(url)
.contentType(MediaType.APPLICATION_JSON)
.content(body)
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isUnprocessableEntity())
.andExpect(jsonPath("$.error", is("AsyncRequired")));
}
@Test
public void deleteServiceAsyncRequredShoudlFailWith422() throws Exception{
ServiceInstance instance = ServiceInstanceFixture.getServiceInstance();
when(serviceInstanceService.deleteServiceInstance(any(DeleteServiceInstanceRequest.class)))
.thenThrow(new ServiceBrokerAsyncRequiredException("Msg"));
String url = ServiceInstanceController.BASE_PATH + "/" + instance.getServiceInstanceId()
+ "?service_id=" + instance.getServiceDefinitionId()
+ "&plan_id=" + instance.getPlanId();
mockMvc.perform(delete(url)
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isUnprocessableEntity())
.andExpect(jsonPath("$.error", is("AsyncRequired")));
}
@Test
public void updateServiceAsyncRequredShoudlFailWith422() throws Exception {
ServiceInstance instance = ServiceInstanceFixture.getServiceInstance();
when(serviceInstanceService.updateServiceInstance(any(UpdateServiceInstanceRequest.class)))
.thenThrow(new ServiceBrokerAsyncRequiredException("msg"));
String url =
ServiceInstanceController.BASE_PATH + "/" + instance.getServiceInstanceId() + "?service_id="
+ instance.getServiceDefinitionId() + "&plan_id=" + instance.getPlanId();
String body = ServiceInstanceFixture.getUpdateServiceInstanceRequestJson();
mockMvc.perform(
patch(url).contentType(MediaType.APPLICATION_JSON).content(body)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isUnprocessableEntity())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.error", is("AsyncRequired")));
}
@Test
public void itShouldPassAnAsyncCreateServiceRequestAndReturn202() throws Exception {
ServiceInstance instance = ServiceInstanceFixture.getServiceInstance()
.withLastOperation(new ServiceInstanceLastOperation("Doing stuff", OperationState.IN_PROGRESS))
.withAsync(true);
when(catalogService.getServiceDefinition(any(String.class)))
.thenReturn(ServiceFixture.getService());
when(serviceInstanceService.createServiceInstance(any(CreateServiceInstanceRequest.class)))
.thenReturn(instance);
String url = ServiceInstanceController.BASE_PATH + "/" + instance.getServiceInstanceId();
String body = ServiceInstanceFixture.getCreateServiceInstanceRequestJson();
mockMvc.perform(
put(url)
.param("accepts_incomplete", "true")
.contentType(MediaType.APPLICATION_JSON)
.content(body)
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isAccepted())
.andExpect(jsonPath("last_operation.state", is("in progress")));
}
@Test
public void itShouldNotBeAsyncWhenAcceptsIncompleteParamIsNotPresent() throws Exception {
ServiceInstance instance = ServiceInstanceFixture.getServiceInstance();
when(serviceInstanceService.createServiceInstance(
(CreateServiceInstanceRequest) anySyncRequest())).thenReturn(instance);
when(catalogService.getServiceDefinition(any(String.class))).thenReturn(ServiceFixture.getService());
String url = ServiceInstanceController.BASE_PATH + "/" + instance.getServiceInstanceId();
String body = ServiceInstanceFixture.getCreateServiceInstanceRequestJson();
mockMvc.perform(
put(url)
.contentType(MediaType.APPLICATION_JSON)
.content(body)
.accept(MediaType.APPLICATION_JSON)
).andExpect(status().isCreated());
}
@Test
public void itShouldReturnAnInProgressServiceInstance() throws Exception {
ServiceInstance instance = ServiceInstanceFixture.getServiceInstance();
String url = ServiceInstanceController.BASE_PATH + "/" + instance.getServiceInstanceId() + "/last_operation";
when(serviceInstanceService.getServiceInstance(any(String.class))).thenReturn(
ServiceInstanceFixture.getAsyncServiceInstance().withLastOperation(
new ServiceInstanceLastOperation("In Progress", OperationState.IN_PROGRESS)));
mockMvc.perform(
get(url))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.state", is("in progress")));
}
@Test
public void itShouldReturnAFailedServiceInstance() throws Exception {
ServiceInstance instance = ServiceInstanceFixture.getServiceInstance();
String url = ServiceInstanceController.BASE_PATH + "/" + instance.getServiceInstanceId() + "/last_operation";
when(serviceInstanceService.getServiceInstance(any(String.class))).thenReturn(
ServiceInstanceFixture.getAsyncServiceInstance().withLastOperation(
new ServiceInstanceLastOperation("no working", OperationState.FAILED)));
mockMvc.perform(
get(url))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.state", is("failed")));
}
@Test
public void itShouldReturnASucceededServiceInstance() throws Exception {
ServiceInstance instance = ServiceInstanceFixture.getServiceInstance();
String url = ServiceInstanceController.BASE_PATH + "/" + instance.getServiceInstanceId() + "/last_operation";
when(serviceInstanceService.getServiceInstance(any(String.class))).thenReturn(
ServiceInstanceFixture.getAsyncServiceInstance().withLastOperation(
new ServiceInstanceLastOperation("mucho working", OperationState.SUCCEEDED)));
mockMvc.perform(
get(url))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.state", is("succeeded")));
}
@Test
public void itShouldReturnGoneIfTheServiceInstanceDoesNotExist() throws Exception {
ServiceInstance instance = ServiceInstanceFixture.getServiceInstance();
String url = ServiceInstanceController.BASE_PATH + "/" + instance.getServiceInstanceId() + "/last_operation";
when(serviceInstanceService.getServiceInstance(any(String.class))).thenReturn(null);
mockMvc.perform(
get(url))
.andExpect(status().isGone())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$", is("{}")));
}
@Test
public void itShouldReturn202ForUpdatedInstanceWithAsync() throws Exception {
ServiceInstance instance = ServiceInstanceFixture.getAsyncServiceInstance()
.withAsync(true);
when(serviceInstanceService.updateServiceInstance(any(UpdateServiceInstanceRequest.class)))
.thenReturn(instance);
String url = ServiceInstanceController.BASE_PATH + "/" + instance.getServiceInstanceId();
String body = ServiceInstanceFixture.getUpdateServiceInstanceRequestJson();
mockMvc.perform(
patch(url).contentType(MediaType.APPLICATION_JSON).content(body)
.accept(MediaType.APPLICATION_JSON)).andExpect(status().isAccepted())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$", is("{}")));
}
@Test
public void itShouldReturn422ForAsyncRequired() throws Exception {
ServiceInstance instance = ServiceInstanceFixture.getServiceInstance();
String url = ServiceInstanceController.BASE_PATH + "/" + instance.getServiceInstanceId();
String body = ServiceInstanceFixture.getUpdateServiceInstanceRequestJson();
when(serviceInstanceService.updateServiceInstance(any(UpdateServiceInstanceRequest.class)))
.thenThrow(new ServiceBrokerAsyncRequiredException("msg"));
mockMvc.perform(
patch(url).contentType(MediaType.APPLICATION_JSON).content(body)
.accept(MediaType.APPLICATION_JSON)).andExpect(status().isUnprocessableEntity())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.error", is("AsyncRequired")))
.andExpect(jsonPath("$.description", is("msg")));
}
@Test
public void itShouldReturn202ForAsyncDelete() throws Exception {
ServiceInstance instance = ServiceInstanceFixture.getAsyncServiceInstance()
.withLastOperation(new ServiceInstanceLastOperation("doin stuff", OperationState.IN_PROGRESS))
.withAsync(true);
when(serviceInstanceService.deleteServiceInstance(
(DeleteServiceInstanceRequest) anyAsyncRequest())).thenReturn(instance);
String url = ServiceInstanceController.BASE_PATH + "/" + instance.getServiceInstanceId()
+ "?service_id=" + instance.getServiceDefinitionId()
+ "&plan_id=" + instance.getPlanId()
+ "&accepts_incomplete=true";
mockMvc.perform(delete(url)
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isAccepted())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.last_operation.state", is("in progress"))
);
}
}