feat(cw2): Drone related test
This commit is contained in:
parent
4e87584723
commit
88a316c0f0
4 changed files with 606 additions and 3 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -40,3 +40,4 @@ out/
|
|||
.direnv/
|
||||
.envrc
|
||||
localjson
|
||||
ilp-cw-api/results.json
|
||||
|
|
|
|||
|
|
@ -28,12 +28,17 @@ public class DroneInfoService {
|
|||
public static final String servicePointsEndpoint = "service-points";
|
||||
public static final String restrictedAreasEndpoint = "restricted-areas";
|
||||
|
||||
private final RestTemplate restTemplate = new RestTemplate();
|
||||
private final RestTemplate restTemplate;
|
||||
|
||||
/**
|
||||
* Constructor, handles the base url here.
|
||||
*/
|
||||
public DroneInfoService() {
|
||||
this(new RestTemplate());
|
||||
}
|
||||
|
||||
public DroneInfoService(RestTemplate restTemplate) {
|
||||
this.restTemplate = restTemplate;
|
||||
String baseUrl = System.getenv("ILP_ENDPOINT");
|
||||
if (baseUrl == null || baseUrl.isBlank()) {
|
||||
this.baseUrl =
|
||||
|
|
@ -268,11 +273,12 @@ public class DroneInfoService {
|
|||
}
|
||||
|
||||
public List<Drone> fetchAllDrones() {
|
||||
System.out.println("fetchAllDrones called");
|
||||
String dronesEndpoint = "drones";
|
||||
URI droneUrl = URI.create(baseUrl).resolve(dronesEndpoint);
|
||||
System.out.println("Fetching from URL: " + droneUrl);
|
||||
Drone[] drones = restTemplate.getForObject(droneUrl, Drone[].class);
|
||||
assert drones != null;
|
||||
return Arrays.asList(drones);
|
||||
return drones == null ? new ArrayList<>() : Arrays.asList(drones);
|
||||
}
|
||||
|
||||
public List<RestrictedArea> fetchRestrictedAreas() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,392 @@
|
|||
package io.github.js0ny.ilp_coursework.controller;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import io.github.js0ny.ilp_coursework.data.common.DroneCapability;
|
||||
import io.github.js0ny.ilp_coursework.data.common.LngLat;
|
||||
import io.github.js0ny.ilp_coursework.data.external.Drone;
|
||||
import io.github.js0ny.ilp_coursework.data.request.AttrQueryRequest;
|
||||
import io.github.js0ny.ilp_coursework.data.request.MedDispatchRecRequest;
|
||||
import io.github.js0ny.ilp_coursework.service.DroneAttrComparatorService;
|
||||
import io.github.js0ny.ilp_coursework.service.DroneInfoService;
|
||||
import io.github.js0ny.ilp_coursework.service.PathFinderService;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
@WebMvcTest(DroneController.class)
|
||||
public class DroneControllerTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@MockitoBean
|
||||
private DroneInfoService droneInfoService;
|
||||
|
||||
@MockitoBean
|
||||
private DroneAttrComparatorService droneAttrComparatorService;
|
||||
|
||||
@MockitoBean
|
||||
private PathFinderService pathFinderService;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
objectMapper = new ObjectMapper();
|
||||
objectMapper.registerModule(new JavaTimeModule());
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("GET /dronesWithCooling/{state}")
|
||||
class GetDronesWithCoolingTest {
|
||||
|
||||
final String API_ENDPOINT_BASE = "/api/v1/dronesWithCooling/";
|
||||
|
||||
@Test
|
||||
@DisplayName("true -> 200 OK")
|
||||
void getDronesWithCooling_shouldReturn200AndArrayOfString_whenStateIsTrue()
|
||||
throws Exception {
|
||||
String endpoint = API_ENDPOINT_BASE + "true";
|
||||
List<String> expected = List.of("1", "5", "8", "9");
|
||||
when(
|
||||
droneInfoService.dronesWithCooling(anyBoolean())).thenReturn(expected);
|
||||
var mock = mockMvc.perform(
|
||||
get(endpoint).contentType(MediaType.APPLICATION_JSON));
|
||||
|
||||
mock.andExpect(status().isOk());
|
||||
mock.andExpect(
|
||||
content().json(objectMapper.writeValueAsString(expected)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("false -> 200 OK")
|
||||
void getDronesWithCooling_shouldReturn200AndArrayOfString_whenStateIsFalse()
|
||||
throws Exception {
|
||||
String endpoint = API_ENDPOINT_BASE + "false";
|
||||
List<String> expected = List.of("2", "3", "4", "6", "7", "10");
|
||||
when(
|
||||
droneInfoService.dronesWithCooling(anyBoolean())).thenReturn(expected);
|
||||
var mock = mockMvc.perform(
|
||||
get(endpoint).contentType(MediaType.APPLICATION_JSON));
|
||||
|
||||
mock.andExpect(status().isOk());
|
||||
mock.andExpect(
|
||||
content().json(objectMapper.writeValueAsString(expected)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("-> 400 Bad Request")
|
||||
void getDronesWithCooling_shouldReturn400_whenStateIsInvalid()
|
||||
throws Exception {
|
||||
String endpoint = API_ENDPOINT_BASE + "invalid";
|
||||
mockMvc.perform(
|
||||
get(endpoint).contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isBadRequest());
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("GET /droneDetails/{droneId}")
|
||||
class DroneDetailsTest {
|
||||
|
||||
static final String API_ENDPOINT_BASE = "/api/v1/droneDetails/";
|
||||
|
||||
@Test
|
||||
@DisplayName("-> 200 OK")
|
||||
void getDroneDetails_shouldReturn200AndJson_whenCorrectInput()
|
||||
throws Exception {
|
||||
Drone expected = new Drone("Drone 1", "1",
|
||||
new DroneCapability(true, true, 4.0f, 2000, 0.01f, 4.3f, 6.5f));
|
||||
String endpoint = API_ENDPOINT_BASE + "1";
|
||||
when(
|
||||
droneInfoService.droneDetail(anyString())).thenReturn(expected);
|
||||
var mock = mockMvc.perform(
|
||||
get(endpoint).contentType(MediaType.APPLICATION_JSON));
|
||||
|
||||
mock.andExpect(status().isOk());
|
||||
mock.andExpect(
|
||||
content().json(objectMapper.writeValueAsString(expected)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("-> 404 Not Found")
|
||||
void getDroneDetails_shouldReturn404_whenDroneNotFound()
|
||||
throws Exception {
|
||||
String endpoint = API_ENDPOINT_BASE + "invalidDroneId";
|
||||
when(
|
||||
droneInfoService.droneDetail(anyString())).thenThrow(new IllegalArgumentException());
|
||||
mockMvc.perform(
|
||||
get(endpoint).contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("GET /queryAsPath/{attrName}/{attrVal}")
|
||||
class GetQueryAsPathTests {
|
||||
|
||||
final String API_ENDPOINT_BASE = "/api/v1/queryAsPath/";
|
||||
|
||||
@Test
|
||||
@DisplayName("capacity = 8 -> 200 OK")
|
||||
void getQueryAsPath_shouldReturn200AndArrayOfString_whenCapacityIs8()
|
||||
throws Exception {
|
||||
String attrName = "capacity";
|
||||
String attrVal = "8";
|
||||
List<String> expected = List.of("2", "4", "7", "9");
|
||||
when(droneAttrComparatorService.dronesWithAttribute(attrName, attrVal))
|
||||
.thenReturn(expected);
|
||||
|
||||
mockMvc.perform(get(API_ENDPOINT_BASE + attrName + "/" + attrVal)
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().json(objectMapper.writeValueAsString(expected)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("heating = true -> 200 OK")
|
||||
void getQueryAsPath_shouldReturn200AndArrayOfString_whenHeatingIsTrue()
|
||||
throws Exception {
|
||||
String attrName = "heating";
|
||||
String attrVal = "true";
|
||||
List<String> expected = List.of("1", "2", "4", "5", "6", "7", "9");
|
||||
when(droneAttrComparatorService.dronesWithAttribute(attrName, attrVal))
|
||||
.thenReturn(expected);
|
||||
|
||||
mockMvc.perform(get(API_ENDPOINT_BASE + attrName + "/" + attrVal)
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().json(objectMapper.writeValueAsString(expected)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("cooling = false -> 200 OK")
|
||||
void getQueryAsPath_shouldReturn200AndArrayOfString_whenCoolingIsFalse()
|
||||
throws Exception {
|
||||
String attrName = "cooling";
|
||||
String attrVal = "false";
|
||||
List<String> expected = List.of("2", "3", "4", "6", "7", "10");
|
||||
when(droneAttrComparatorService.dronesWithAttribute(attrName, attrVal))
|
||||
.thenReturn(expected);
|
||||
|
||||
mockMvc.perform(get(API_ENDPOINT_BASE + attrName + "/" + attrVal)
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().json(objectMapper.writeValueAsString(expected)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("maxMoves = 1000 -> 200 OK")
|
||||
void getQueryAsPath_shouldReturn200AndArrayOfString_whenMaxMovesIs1000()
|
||||
throws Exception {
|
||||
String attrName = "maxMoves";
|
||||
String attrVal = "1000";
|
||||
List<String> expected = List.of("2", "4", "7", "9");
|
||||
when(droneAttrComparatorService.dronesWithAttribute(attrName, attrVal))
|
||||
.thenReturn(expected);
|
||||
|
||||
mockMvc.perform(get(API_ENDPOINT_BASE + attrName + "/" + attrVal)
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().json(objectMapper.writeValueAsString(expected)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("invalid = null -> 200 OK (empty list)")
|
||||
void getQueryAsPath_shouldReturn200AndEmptyArrayOfString_whenInvalidAttribute()
|
||||
throws Exception {
|
||||
String attrName = "invalid";
|
||||
String attrVal = "null";
|
||||
List<String> expected = List.of();
|
||||
when(droneAttrComparatorService.dronesWithAttribute(attrName, attrVal))
|
||||
.thenReturn(expected);
|
||||
|
||||
mockMvc.perform(get(API_ENDPOINT_BASE + attrName + "/" + attrVal)
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().json(objectMapper.writeValueAsString(expected)));
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("POST /query")
|
||||
class PostQueryTests {
|
||||
|
||||
final String API_ENDPOINT = "/api/v1/query";
|
||||
|
||||
@Test
|
||||
@DisplayName("three eqs -> 200 OK")
|
||||
void postQuery_shouldReturn200AndArrayOfString_whenThreeEqualsConditions()
|
||||
throws Exception {
|
||||
AttrQueryRequest req1 = new AttrQueryRequest("capacity", "=", "20");
|
||||
AttrQueryRequest req2 = new AttrQueryRequest("heating", "=", "false");
|
||||
AttrQueryRequest req3 = new AttrQueryRequest("cooling", "=", "true");
|
||||
AttrQueryRequest[] requestBody = {req1, req2, req3};
|
||||
List<String> expected = List.of("8");
|
||||
|
||||
when(droneAttrComparatorService.dronesSatisfyingAttributes(any(AttrQueryRequest[].class)))
|
||||
.thenReturn(expected);
|
||||
|
||||
mockMvc.perform(post(API_ENDPOINT)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(requestBody)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().json(objectMapper.writeValueAsString(expected)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("GT LT -> 200 OK")
|
||||
void postQuery_shouldReturn200AndArrayOfString_whenGtLtConditions()
|
||||
throws Exception {
|
||||
AttrQueryRequest req1 = new AttrQueryRequest("capacity", ">", "8");
|
||||
AttrQueryRequest req2 = new AttrQueryRequest("maxMoves", "<", "2000");
|
||||
AttrQueryRequest[] requestBody = {req1, req2};
|
||||
List<String> expected = List.of("5", "10");
|
||||
|
||||
when(droneAttrComparatorService.dronesSatisfyingAttributes(any(AttrQueryRequest[].class)))
|
||||
.thenReturn(expected);
|
||||
|
||||
mockMvc.perform(post(API_ENDPOINT)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(requestBody)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().json(objectMapper.writeValueAsString(expected)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("GT LT -contradict -> 200 OK (empty list)")
|
||||
void postQuery_shouldReturn200AndEmptyArrayOfString_whenContradictoryConditions()
|
||||
throws Exception {
|
||||
AttrQueryRequest req1 = new AttrQueryRequest("capacity", ">", "8");
|
||||
AttrQueryRequest req2 = new AttrQueryRequest("capacity", "<", "8");
|
||||
AttrQueryRequest[] requestBody = {req1, req2};
|
||||
List<String> expected = List.of();
|
||||
|
||||
when(droneAttrComparatorService.dronesSatisfyingAttributes(any(AttrQueryRequest[].class)))
|
||||
.thenReturn(expected);
|
||||
|
||||
mockMvc.perform(post(API_ENDPOINT)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(requestBody)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().json(objectMapper.writeValueAsString(expected)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("GT LT EQ -> 200 OK")
|
||||
void postQuery_shouldReturn200AndArrayOfString_whenGtLtEqConditions()
|
||||
throws Exception {
|
||||
AttrQueryRequest req1 = new AttrQueryRequest("capacity", ">", "8");
|
||||
AttrQueryRequest req2 = new AttrQueryRequest("maxMoves", "<", "2000");
|
||||
AttrQueryRequest req3 = new AttrQueryRequest("cooling", "=", "true");
|
||||
AttrQueryRequest[] requestBody = {req1, req2, req3};
|
||||
List<String> expected = List.of("5");
|
||||
|
||||
when(droneAttrComparatorService.dronesSatisfyingAttributes(any(AttrQueryRequest[].class)))
|
||||
.thenReturn(expected);
|
||||
|
||||
mockMvc.perform(post(API_ENDPOINT)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(requestBody)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().json(objectMapper.writeValueAsString(expected)));
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("POST /queryAvailableDrones")
|
||||
class PostQueryAvailableDronesTests {
|
||||
|
||||
final String API_ENDPOINT = "/api/v1/queryAvailableDrones";
|
||||
|
||||
@Test
|
||||
@DisplayName("Example -> 200 OK")
|
||||
void postQueryAvailableDrones_shouldReturn200AndArrayOfString_whenExampleRequest()
|
||||
throws Exception {
|
||||
var reqs = new MedDispatchRecRequest.MedRequirement(0.75f, false, true, 13.5f);
|
||||
var delivery = new LngLat(-3.00, 55.121);
|
||||
var record = new MedDispatchRecRequest(123, LocalDate.parse("2025-12-22"), LocalTime.parse("14:30"), reqs, delivery);
|
||||
MedDispatchRecRequest[] requestBody = {record};
|
||||
List<String> expected = List.of("1", "2", "6", "7", "9");
|
||||
|
||||
when(droneInfoService.dronesMatchesRequirements(any(MedDispatchRecRequest[].class)))
|
||||
.thenReturn(expected);
|
||||
|
||||
mockMvc.perform(post(API_ENDPOINT)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(requestBody)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().json(objectMapper.writeValueAsString(expected)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Treat Null as False (Cooling) -> 200 OK")
|
||||
void postQueryAvailableDrones_shouldReturn200AndArrayOfString_whenCoolingIsNull()
|
||||
throws Exception {
|
||||
var requestMap = Map.of(
|
||||
"id", 123,
|
||||
"date", "2025-12-22",
|
||||
"time", "14:30",
|
||||
"requirements", Map.of(
|
||||
"capacity", 0.75,
|
||||
"heating", true,
|
||||
"maxCost", 13.5
|
||||
)
|
||||
);
|
||||
List<String> expected = List.of("1", "2", "6", "7", "9");
|
||||
|
||||
when(droneInfoService.dronesMatchesRequirements(any(MedDispatchRecRequest[].class)))
|
||||
.thenReturn(expected);
|
||||
|
||||
mockMvc.perform(post(API_ENDPOINT)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(new Object[]{requestMap})))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().json(objectMapper.writeValueAsString(expected)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Complex -> 200 OK")
|
||||
void postQueryAvailableDrones_shouldReturn200AndArrayOfString_whenComplexRequest()
|
||||
throws Exception {
|
||||
var reqs1 = new MedDispatchRecRequest.MedRequirement(0.75f, false, true, 13.5f);
|
||||
var delivery1 = new LngLat(-3.00, 55.121);
|
||||
var record1 = new MedDispatchRecRequest(123, LocalDate.parse("2025-12-22"), LocalTime.parse("14:30"), reqs1, delivery1);
|
||||
|
||||
var reqs2 = new MedDispatchRecRequest.MedRequirement(0.75f, false, true, 13.5f);
|
||||
var delivery2 = new LngLat(-3.00, 55.121);
|
||||
var record2 = new MedDispatchRecRequest(456, LocalDate.parse("2025-12-25"), LocalTime.parse("11:30"), reqs2, delivery2);
|
||||
|
||||
MedDispatchRecRequest[] requestBody = {record1, record2};
|
||||
List<String> expected = List.of("2", "7", "9");
|
||||
|
||||
when(droneInfoService.dronesMatchesRequirements(any(MedDispatchRecRequest[].class)))
|
||||
.thenReturn(expected);
|
||||
|
||||
mockMvc.perform(post(API_ENDPOINT)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(requestBody)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().json(objectMapper.writeValueAsString(expected)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
package io.github.js0ny.ilp_coursework.service;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import io.github.js0ny.ilp_coursework.data.common.DroneAvailability;
|
||||
import io.github.js0ny.ilp_coursework.data.common.DroneCapability;
|
||||
import io.github.js0ny.ilp_coursework.data.common.LngLat;
|
||||
import io.github.js0ny.ilp_coursework.data.common.TimeWindow;
|
||||
import io.github.js0ny.ilp_coursework.data.external.Drone;
|
||||
import io.github.js0ny.ilp_coursework.data.external.ServicePointDrones;
|
||||
import io.github.js0ny.ilp_coursework.data.request.MedDispatchRecRequest;
|
||||
import java.net.URI;
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class DroneInfoServiceTest {
|
||||
|
||||
@Mock
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
private DroneInfoService droneInfoService;
|
||||
|
||||
private final String baseUrl = "http://localhost:8080/";
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
droneInfoService = new DroneInfoService(restTemplate);
|
||||
ReflectionTestUtils.setField(droneInfoService, "baseUrl", baseUrl);
|
||||
}
|
||||
|
||||
private Drone[] getMockDrones() {
|
||||
return new Drone[] {
|
||||
new Drone("Drone 1", "1", new DroneCapability(true, true, 10, 1000, 1, 1, 1)),
|
||||
new Drone("Drone 2", "2", new DroneCapability(false, true, 20, 2000, 2, 2, 2)),
|
||||
new Drone("Drone 3", "3", new DroneCapability(false, false, 30, 3000, 3, 3, 3))
|
||||
};
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("dronesWithCooling(boolean) tests")
|
||||
class DronesWithCoolingTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Should return drones with cooling")
|
||||
void dronesWithCooling_shouldReturnDronesWithCooling() {
|
||||
// Arrange
|
||||
when(restTemplate.getForObject(URI.create(baseUrl + "drones"), Drone[].class))
|
||||
.thenReturn(getMockDrones());
|
||||
|
||||
// Act
|
||||
List<String> result = droneInfoService.dronesWithCooling(true);
|
||||
|
||||
// Assert
|
||||
assertThat(result).containsExactly("1");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should return drones without cooling")
|
||||
void dronesWithCooling_shouldReturnDronesWithoutCooling() {
|
||||
// Arrange
|
||||
when(restTemplate.getForObject(URI.create(baseUrl + "drones"), Drone[].class))
|
||||
.thenReturn(getMockDrones());
|
||||
|
||||
// Act
|
||||
List<String> result = droneInfoService.dronesWithCooling(false);
|
||||
|
||||
// Assert
|
||||
assertThat(result).containsExactly("2", "3");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should return empty list when API returns null")
|
||||
void dronesWithCooling_shouldReturnEmptyList_whenApiReturnsNull() {
|
||||
// Arrange
|
||||
when(restTemplate.getForObject(URI.create(baseUrl + "drones"), Drone[].class))
|
||||
.thenReturn(null);
|
||||
|
||||
// Act
|
||||
List<String> result = droneInfoService.dronesWithCooling(true);
|
||||
|
||||
// Assert
|
||||
assertThat(result).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("droneDetail(String) tests")
|
||||
class DroneDetailTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Should return correct drone details")
|
||||
void droneDetail_shouldReturnCorrectDrone() {
|
||||
// Arrange
|
||||
when(restTemplate.getForObject(URI.create(baseUrl + "drones"), Drone[].class))
|
||||
.thenReturn(getMockDrones());
|
||||
|
||||
// Act
|
||||
Drone result = droneInfoService.droneDetail("2");
|
||||
|
||||
// Assert
|
||||
assertThat(result.id()).isEqualTo("2");
|
||||
assertThat(result.name()).isEqualTo("Drone 2");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should throw exception for non-existent drone")
|
||||
void droneDetail_shouldThrowException_forNonExistentDrone() {
|
||||
// Arrange
|
||||
when(restTemplate.getForObject(URI.create(baseUrl + "drones"), Drone[].class))
|
||||
.thenReturn(getMockDrones());
|
||||
|
||||
// Act & Assert
|
||||
assertThatThrownBy(() -> droneInfoService.droneDetail("4"))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("drone with that ID cannot be found");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("dronesMatchesRequirements(MedDispatchRecRequest[]) tests")
|
||||
class DronesMatchesRequirementsTests {
|
||||
private ServicePointDrones[] getMockServicePointDrones() {
|
||||
TimeWindow[] timeWindows = { new TimeWindow(DayOfWeek.MONDAY, LocalTime.of(9, 0), LocalTime.of(17, 0)) };
|
||||
DroneAvailability drone1Avail = new DroneAvailability("1", timeWindows);
|
||||
ServicePointDrones spd = new ServicePointDrones(1, new DroneAvailability[] { drone1Avail });
|
||||
return new ServicePointDrones[] { spd };
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should return drones matching a single requirement")
|
||||
void dronesMatchesRequirements_shouldReturnMatchingDrones_forSingleRequirement() {
|
||||
// Arrange
|
||||
var drones = new Drone[] {
|
||||
new Drone("Drone 1", "1", new DroneCapability(true, true, 10, 1000, 1, 1, 1)),
|
||||
new Drone("Drone 2", "2", new DroneCapability(false, true, 5, 2000, 2, 2, 2))
|
||||
};
|
||||
when(restTemplate.getForObject(URI.create(baseUrl + "drones"), Drone[].class)).thenReturn(drones);
|
||||
when(restTemplate.getForObject(URI.create(baseUrl + "drones-for-service-points"),
|
||||
ServicePointDrones[].class)).thenReturn(getMockServicePointDrones());
|
||||
|
||||
var requirement = new MedDispatchRecRequest.MedRequirement(8, true, false, 100);
|
||||
var record = new MedDispatchRecRequest(1, LocalDate.now().with(DayOfWeek.MONDAY), LocalTime.of(10, 0),
|
||||
requirement, new LngLat(0, 0));
|
||||
|
||||
// Act
|
||||
List<String> result = droneInfoService.dronesMatchesRequirements(new MedDispatchRecRequest[] { record });
|
||||
|
||||
// Assert
|
||||
assertThat(result).containsExactly("1");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should return empty list if no drones match")
|
||||
void dronesMatchesRequirements_shouldReturnEmptyList_whenNoDronesMatch() {
|
||||
// Arrange
|
||||
var drones = new Drone[] {
|
||||
new Drone("Drone 1", "1", new DroneCapability(true, true, 5, 1000, 1, 1, 1)),
|
||||
new Drone("Drone 2", "2", new DroneCapability(false, true, 5, 2000, 2, 2, 2))
|
||||
};
|
||||
when(restTemplate.getForObject(URI.create(baseUrl + "drones"), Drone[].class)).thenReturn(drones);
|
||||
// No need to mock drones-for-service-points as it won't be called
|
||||
|
||||
var requirement = new MedDispatchRecRequest.MedRequirement(10, true, false, 100);
|
||||
var record = new MedDispatchRecRequest(1, LocalDate.now().with(DayOfWeek.MONDAY), LocalTime.of(10, 0),
|
||||
requirement, new LngLat(0, 0));
|
||||
|
||||
// Act
|
||||
List<String> result = droneInfoService.dronesMatchesRequirements(new MedDispatchRecRequest[] { record });
|
||||
|
||||
// Assert
|
||||
assertThat(result).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should return all drones if requirements are null or empty")
|
||||
void dronesMatchesRequirements_shouldReturnAllDrones_forNullOrEmptyRequirements() {
|
||||
// Arrange
|
||||
when(restTemplate.getForObject(URI.create(baseUrl + "drones"), Drone[].class))
|
||||
.thenReturn(getMockDrones());
|
||||
|
||||
// Act
|
||||
List<String> resultNull = droneInfoService.dronesMatchesRequirements(null);
|
||||
List<String> resultEmpty = droneInfoService.dronesMatchesRequirements(new MedDispatchRecRequest[0]);
|
||||
|
||||
// Assert
|
||||
assertThat(resultNull).containsExactly("1", "2", "3");
|
||||
assertThat(resultEmpty).containsExactly("1", "2", "3");
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue