From 7a2fd40df22a282281e6519c901b555e4c1b401f Mon Sep 17 00:00:00 2001 From: Lukas Connolly Date: Sat, 8 Jun 2024 10:37:11 +0200 Subject: [PATCH 01/13] TEST: NAV-77 - Start implementing tests for REST controller. --- .../app/controller/RoutingControllerTest.java | 159 ++++++++++++++++++ .../app/service/ServiceConfigParserIT.java | 39 +++++ 2 files changed, 198 insertions(+) create mode 100644 src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java create mode 100644 src/test/java/ch/naviqore/app/service/ServiceConfigParserIT.java diff --git a/src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java b/src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java new file mode 100644 index 00000000..83f44a65 --- /dev/null +++ b/src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java @@ -0,0 +1,159 @@ +package ch.naviqore.app.controller; + +import ch.naviqore.app.dto.Connection; +import ch.naviqore.service.PublicTransitService; +import ch.naviqore.service.Stop; +import ch.naviqore.service.exception.StopNotFoundException; +import ch.naviqore.utils.spatial.GeoCoordinate; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.web.server.ResponseStatusException; + +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class RoutingControllerTest { + + @Mock + private PublicTransitService publicTransitService; + + @InjectMocks + private RoutingController routingController; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + } + + @Test + void testGetConnections_WithValidSourceAndTargetStopIds() throws StopNotFoundException { + // Arrange + String sourceStopId = "sourceStopId"; + String targetStopId = "targetStopId"; + LocalDateTime departureDateTime = LocalDateTime.now(); + + Stop sourceStop = mock(Stop.class); + Stop targetStop = mock(Stop.class); + + try { + when(publicTransitService.getStopById(sourceStopId)).thenReturn(sourceStop); + when(publicTransitService.getStopById(targetStopId)).thenReturn(targetStop); + } catch (StopNotFoundException e) { + fail("StopNotFoundException was thrown", e); + } + when(publicTransitService.getConnections(eq(sourceStop), eq(targetStop), any(), any(), any())).thenReturn( + Collections.emptyList()); + + // Act + List connections = routingController.getConnections(sourceStopId, -1.0, -1.0, targetStopId, -1.0, + -1.0, departureDateTime, 30, 2, 120, 5); + + // Assert + assertNotNull(connections); + } + + @Test + void testGetConnections_WithoutSourceStopIdButWithCoordinates() { + // Arrange + double sourceLatitude = 46.2044; + double sourceLongitude = 6.1432; + String targetStopId = "targetStopId"; + LocalDateTime departureDateTime = LocalDateTime.now(); + + Stop targetStop = mock(Stop.class); + + try { + when(publicTransitService.getStopById(targetStopId)).thenReturn(targetStop); + } catch (StopNotFoundException e) { + fail("StopNotFoundException was thrown", e); + } + when(publicTransitService.getConnections(any(GeoCoordinate.class), eq(targetStop), any(), any(), + any())).thenReturn(Collections.emptyList()); + + // Act + List connections = routingController.getConnections(null, sourceLatitude, sourceLongitude, + targetStopId, -1.0, -1.0, departureDateTime, 30, 2, 120, 5); + + // Assert + assertNotNull(connections); + } + + @Test + void testGetConnections_MissingSourceAndCoordinates() { + // Act & Assert + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + routingController.getConnections(null, -1.0, -1.0, "targetStopId", -1.0, -1.0, LocalDateTime.now(), 30, 2, + 120, 5); + }); + assertEquals("Either sourceStopId or sourceLatitude and sourceLongitude must be provided.", + exception.getReason()); + } + + @Test + void testGetConnections_MissingTargetAndCoordinates() { + // Act & Assert + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + routingController.getConnections("sourceStopId", -1.0, -1.0, null, -1.0, -1.0, LocalDateTime.now(), 30, 2, + 120, 5); + }); + assertEquals("Either targetStopId or targetLatitude and targetLongitude must be provided.", + exception.getReason()); + } + + @Test + void testGetConnection_InvalidCoordinates() { + // Act & Assert + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + routingController.getConnections(null, 91, -181, null, 32, 32, LocalDateTime.now(), 30, 2, 120, 5); + }); + assertEquals("Coordinates must be valid, Latitude between -90 and 90 and Longitude between -180 and 180.", + exception.getReason()); + } + + @Test + void testGetConnections_InvalidMaxTransferNumber() { + // Act & Assert + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + routingController.getConnections(null, 0, 0, null, 0, 0, LocalDateTime.now(), 30, -2, 120, 5); + }); + assertEquals("Max transfer number must be greater than or equal to 0.", exception.getReason()); + } + + @Test + void testGetConnections_InvalidMaxWalkingDuration() { + // Act & Assert + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + routingController.getConnections(null, 0, 0, null, 0, 0, LocalDateTime.now(), -30, 2, 120, 5); + }); + assertEquals("Max walking duration must be greater than or equal to 0.", exception.getReason()); + } + + @Test + void testGetConnections_InvalidMaxTravelTime() { + // Act & Assert + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + routingController.getConnections(null, 0, 0, null, 0, 0, LocalDateTime.now(), 30, 2, -120, 5); + }); + assertEquals("Max travel time must be greater than or equal to 0.", exception.getReason()); + } + + @Test + void testGetConnections_InvalidMinTransferTime() { + // Act & Assert + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + routingController.getConnections(null, 0, 0, null, 0, 0, LocalDateTime.now(), 30, 2, 120, -5); + }); + assertEquals("Min transfer time must be greater than or equal to 0.", exception.getReason()); + } + +} diff --git a/src/test/java/ch/naviqore/app/service/ServiceConfigParserIT.java b/src/test/java/ch/naviqore/app/service/ServiceConfigParserIT.java new file mode 100644 index 00000000..fb9c620d --- /dev/null +++ b/src/test/java/ch/naviqore/app/service/ServiceConfigParserIT.java @@ -0,0 +1,39 @@ +package ch.naviqore.app.service; + +import ch.naviqore.service.config.ServiceConfig; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class ServiceConfigParserIT { + + @Test + void testServiceConfigParser_withValidInputs() { + String gtfsUrl = "src/test/resources/ch/naviqore/gtfs/schedule/sample-feed-1.zip"; + int minimumTransferTime = 200; + int maxWalkingDistance = 600; + int walkingSpeed = 4000; + String walkingCalculatorType = "BEE_LINE_DISTANCE"; + + ServiceConfigParser parser = new ServiceConfigParser(gtfsUrl, minimumTransferTime, maxWalkingDistance, + walkingSpeed, walkingCalculatorType); + + // check that the service config has been loaded correctly + ServiceConfig config = parser.getServiceConfig(); + assertEquals(gtfsUrl, config.getGtfsUrl()); + assertEquals(minimumTransferTime, config.getMinimumTransferTime()); + assertEquals(maxWalkingDistance, config.getMaxWalkingDistance()); + assertEquals(walkingSpeed, config.getWalkingSpeed()); + assertEquals(ServiceConfig.WalkCalculatorType.BEE_LINE_DISTANCE, config.getWalkCalculatorType()); + } + + @Test + void testServiceConfigParser_withInvalidWalkCalculatorType() { + // check that the service config has been loaded correctly + assertThrows(IllegalArgumentException.class, + () -> new ServiceConfigParser("src/test/resources/ch/naviqore/gtfs/schedule/invalidSchedule.zip", 200, + 600, 4000, "INVALID")); + } + +} From 0d3970f58f0abc1152c5bb64d8359d75e9f0e254 Mon Sep 17 00:00:00 2001 From: Lukas Connolly Date: Sat, 8 Jun 2024 11:12:48 +0200 Subject: [PATCH 02/13] ENH: NAV-77 - More validation in Routing Controller and fix coordinate logic. --- .../app/controller/RoutingController.java | 73 ++++++++++++++----- 1 file changed, 56 insertions(+), 17 deletions(-) diff --git a/src/main/java/ch/naviqore/app/controller/RoutingController.java b/src/main/java/ch/naviqore/app/controller/RoutingController.java index 4d603718..cfae96e8 100644 --- a/src/main/java/ch/naviqore/app/controller/RoutingController.java +++ b/src/main/java/ch/naviqore/app/controller/RoutingController.java @@ -37,28 +37,34 @@ public RoutingController(PublicTransitService service) { @GetMapping("/connections") public List getConnections(@RequestParam(required = false) String sourceStopId, - @RequestParam(required = false, defaultValue = "-1.0") double sourceLatitude, - @RequestParam(required = false, defaultValue = "-1.0") double sourceLongitude, + @RequestParam(required = false, defaultValue = "-91.0") double sourceLatitude, + @RequestParam(required = false, defaultValue = "-181.0") double sourceLongitude, @RequestParam(required = false) String targetStopId, - @RequestParam(required = false, defaultValue = "-1.0") double targetLatitude, - @RequestParam(required = false, defaultValue = "-1.0") double targetLongitude, + @RequestParam(required = false, defaultValue = "-91.0") double targetLatitude, + @RequestParam(required = false, defaultValue = "-181.0") double targetLongitude, @RequestParam(required = false) LocalDateTime departureDateTime, @RequestParam(required = false, defaultValue = "2147483647") int maxWalkingDuration, @RequestParam(required = false, defaultValue = "2147483647") int maxTransferNumber, @RequestParam(required = false, defaultValue = "2147483647") int maxTravelTime, @RequestParam(required = false, defaultValue = "0") int minTransferTime) { + + GeoCoordinate sourceCoordinate = null; + GeoCoordinate targetCoordinate = null; + if (sourceStopId == null) { - if (sourceLatitude < 0 || sourceLongitude < 0) { + if (sourceLatitude == -91.0 || sourceLongitude == -181.0) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Either sourceStopId or sourceLatitude and sourceLongitude must be provided."); } + sourceCoordinate = validateCoordinate(sourceLatitude, sourceLongitude); } if (targetStopId == null) { - if (targetLatitude < 0 || targetLongitude < 0) { + if (targetLatitude == -91.0 || targetLongitude == -181.0) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Either targetStopId or targetLatitude and targetLongitude must be provided."); } + targetCoordinate = validateCoordinate(targetLatitude, targetLongitude); } if (departureDateTime == null) { @@ -68,9 +74,7 @@ public List getConnections(@RequestParam(required = false) String so Stop sourceStop = sourceStopId != null ? getStop(sourceStopId) : null; Stop targetStop = targetStopId != null ? getStop(targetStopId) : null; - GeoCoordinate sourceCoordinate = sourceStop == null ? new GeoCoordinate(sourceLatitude, sourceLongitude) : null; - GeoCoordinate targetCoordinate = targetStop == null ? new GeoCoordinate(targetLatitude, targetLongitude) : null; - + validateQueryParams(maxWalkingDuration, maxTransferNumber, maxTravelTime, minTransferTime); ConnectionQueryConfig config = new ConnectionQueryConfig(maxWalkingDuration, minTransferTime, maxTransferNumber, maxTravelTime); @@ -94,28 +98,35 @@ public List getConnections(@RequestParam(required = false) String so @GetMapping("/isolines") public List getIsolines(@RequestParam(required = false) String sourceStopId, - @RequestParam(required = false, defaultValue = "-1.0") double sourceLatitude, - @RequestParam(required = false, defaultValue = "-1.0") double sourceLongitude, + @RequestParam(required = false, defaultValue = "-91") double sourceLatitude, + @RequestParam(required = false, defaultValue = "-181") double sourceLongitude, @RequestParam(required = false) LocalDateTime departureDateTime, @RequestParam(required = false, defaultValue = "2147483647") int maxWalkingDuration, @RequestParam(required = false, defaultValue = "2147483647") int maxTransferNumber, @RequestParam(required = false, defaultValue = "2147483647") int maxTravelTime, @RequestParam(required = false, defaultValue = "0") int minTransferTime) { + + GeoCoordinate sourceCoordinate = null; if (sourceStopId == null) { - if (sourceLatitude < 0 || sourceLongitude < 0) { + if (sourceLatitude == -91.0 || sourceLongitude == -181.0) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Either sourceStopId or sourceLatitude and sourceLongitude must be provided."); } - throw new ResponseStatusException(HttpStatus.NOT_IMPLEMENTED, - "Location based routing is not implemented yet."); + sourceCoordinate = validateCoordinate(sourceLatitude, sourceLongitude); } - Stop sourceStop = getStop(sourceStopId); + Stop sourceStop = sourceStopId != null ? getStop(sourceStopId) : null; + + validateQueryParams(maxWalkingDuration, maxTransferNumber, maxTravelTime, minTransferTime); ConnectionQueryConfig config = new ConnectionQueryConfig(maxWalkingDuration, minTransferTime, maxTransferNumber, maxTravelTime); - Map connections = service.getIsolines(sourceStop, departureDateTime, - config); + Map connections; + if (sourceStop != null) { + connections = service.getIsolines(sourceStop, departureDateTime, config); + } else { + connections = service.getIsolines(sourceCoordinate, departureDateTime, config); + } List arrivals = new ArrayList<>(); @@ -136,4 +147,32 @@ private ch.naviqore.service.Stop getStop(String stopId) { } } + private static GeoCoordinate validateCoordinate(double latitude, double longitude) { + try { + return new GeoCoordinate(latitude, longitude); + } catch (IllegalArgumentException e) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, + "Coordinates must be valid, Latitude between -90 and 90 and Longitude between -180 and 180."); + } + } + + private static void validateQueryParams(int maxWalkingDuration, int maxTransferNumber, int maxTravelTime, + int minTransferTime) { + if (maxWalkingDuration < 0) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, + "Max walking duration must be greater than or equal to 0."); + } + if (maxTransferNumber < 0) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, + "Max transfer number must be greater than or equal to 0."); + } + if (maxTravelTime <= 0) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Max travel time must be greater than 0."); + } + if (minTransferTime < 0) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, + "Min transfer time must be greater than or equal to 0."); + } + } + } From baf7085da775e62ff3261385d654127500af1b33 Mon Sep 17 00:00:00 2001 From: Lukas Connolly Date: Sat, 8 Jun 2024 11:13:39 +0200 Subject: [PATCH 03/13] TEST: NAV-77 - Adjust tests to implementation in Routing controller. --- .../ch/naviqore/app/controller/RoutingControllerTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java b/src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java index 83f44a65..9e4f28e8 100644 --- a/src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java +++ b/src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java @@ -92,7 +92,7 @@ void testGetConnections_WithoutSourceStopIdButWithCoordinates() { void testGetConnections_MissingSourceAndCoordinates() { // Act & Assert ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - routingController.getConnections(null, -1.0, -1.0, "targetStopId", -1.0, -1.0, LocalDateTime.now(), 30, 2, + routingController.getConnections(null, -91.0, -181.0, "targetStopId", -91.0, -181.0, LocalDateTime.now(), 30, 2, 120, 5); }); assertEquals("Either sourceStopId or sourceLatitude and sourceLongitude must be provided.", @@ -103,7 +103,7 @@ void testGetConnections_MissingSourceAndCoordinates() { void testGetConnections_MissingTargetAndCoordinates() { // Act & Assert ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - routingController.getConnections("sourceStopId", -1.0, -1.0, null, -1.0, -1.0, LocalDateTime.now(), 30, 2, + routingController.getConnections("sourceStopId", -91.0, -181.0, null, -91.0, -181.0, LocalDateTime.now(), 30, 2, 120, 5); }); assertEquals("Either targetStopId or targetLatitude and targetLongitude must be provided.", @@ -114,7 +114,7 @@ void testGetConnections_MissingTargetAndCoordinates() { void testGetConnection_InvalidCoordinates() { // Act & Assert ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - routingController.getConnections(null, 91, -181, null, 32, 32, LocalDateTime.now(), 30, 2, 120, 5); + routingController.getConnections(null, 91, 181, null, 32, 32, LocalDateTime.now(), 30, 2, 120, 5); }); assertEquals("Coordinates must be valid, Latitude between -90 and 90 and Longitude between -180 and 180.", exception.getReason()); @@ -144,7 +144,7 @@ void testGetConnections_InvalidMaxTravelTime() { ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { routingController.getConnections(null, 0, 0, null, 0, 0, LocalDateTime.now(), 30, 2, -120, 5); }); - assertEquals("Max travel time must be greater than or equal to 0.", exception.getReason()); + assertEquals("Max travel time must be greater than 0.", exception.getReason()); } @Test From 18fc68bd366853a16bf9d476c2289cb6b15833bf Mon Sep 17 00:00:00 2001 From: Lukas Connolly Date: Sat, 8 Jun 2024 11:33:09 +0200 Subject: [PATCH 04/13] TEST: NAV-77 - Add test for invalid stop id. --- .../app/controller/RoutingControllerTest.java | 40 ++++++++++++++++--- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java b/src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java index 9e4f28e8..2c50ec1c 100644 --- a/src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java +++ b/src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java @@ -10,6 +10,7 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.springframework.http.HttpStatusCode; import org.springframework.web.server.ResponseStatusException; import java.time.LocalDateTime; @@ -36,7 +37,7 @@ void setUp() { } @Test - void testGetConnections_WithValidSourceAndTargetStopIds() throws StopNotFoundException { + void testGetConnections_WithValidSourceAndTargetStopIds() { // Arrange String sourceStopId = "sourceStopId"; String targetStopId = "targetStopId"; @@ -88,26 +89,50 @@ void testGetConnections_WithoutSourceStopIdButWithCoordinates() { assertNotNull(connections); } + @Test + void testGetConnections_InvalidStopId() { + // Arrange + String invalidStopId = "invalidStopId"; + String targetStopId = "targetStopId"; + Stop targetStop = mock(Stop.class); + + try { + when(publicTransitService.getStopById(invalidStopId)).thenThrow(new StopNotFoundException(invalidStopId)); + when(publicTransitService.getStopById(targetStopId)).thenReturn(targetStop); + } catch (StopNotFoundException e) { + fail("StopNotFoundException was thrown", e); + } + // Act & Assert + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + routingController.getConnections(invalidStopId, -91.0, -181.0, targetStopId, -91.0, -181.0, + LocalDateTime.now(), 30, 2, 120, 5); + }); + assertEquals("Stop not found", exception.getReason()); + assertEquals(HttpStatusCode.valueOf(404), exception.getStatusCode()); + } + @Test void testGetConnections_MissingSourceAndCoordinates() { // Act & Assert ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - routingController.getConnections(null, -91.0, -181.0, "targetStopId", -91.0, -181.0, LocalDateTime.now(), 30, 2, - 120, 5); + routingController.getConnections(null, -91.0, -181.0, "targetStopId", -91.0, -181.0, LocalDateTime.now(), + 30, 2, 120, 5); }); assertEquals("Either sourceStopId or sourceLatitude and sourceLongitude must be provided.", exception.getReason()); + assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); } @Test void testGetConnections_MissingTargetAndCoordinates() { // Act & Assert ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - routingController.getConnections("sourceStopId", -91.0, -181.0, null, -91.0, -181.0, LocalDateTime.now(), 30, 2, - 120, 5); + routingController.getConnections("sourceStopId", -91.0, -181.0, null, -91.0, -181.0, LocalDateTime.now(), + 30, 2, 120, 5); }); assertEquals("Either targetStopId or targetLatitude and targetLongitude must be provided.", exception.getReason()); + assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); } @Test @@ -118,6 +143,7 @@ void testGetConnection_InvalidCoordinates() { }); assertEquals("Coordinates must be valid, Latitude between -90 and 90 and Longitude between -180 and 180.", exception.getReason()); + assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); } @Test @@ -127,6 +153,7 @@ void testGetConnections_InvalidMaxTransferNumber() { routingController.getConnections(null, 0, 0, null, 0, 0, LocalDateTime.now(), 30, -2, 120, 5); }); assertEquals("Max transfer number must be greater than or equal to 0.", exception.getReason()); + assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); } @Test @@ -136,6 +163,7 @@ void testGetConnections_InvalidMaxWalkingDuration() { routingController.getConnections(null, 0, 0, null, 0, 0, LocalDateTime.now(), -30, 2, 120, 5); }); assertEquals("Max walking duration must be greater than or equal to 0.", exception.getReason()); + assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); } @Test @@ -145,6 +173,7 @@ void testGetConnections_InvalidMaxTravelTime() { routingController.getConnections(null, 0, 0, null, 0, 0, LocalDateTime.now(), 30, 2, -120, 5); }); assertEquals("Max travel time must be greater than 0.", exception.getReason()); + assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); } @Test @@ -154,6 +183,7 @@ void testGetConnections_InvalidMinTransferTime() { routingController.getConnections(null, 0, 0, null, 0, 0, LocalDateTime.now(), 30, 2, 120, -5); }); assertEquals("Min transfer time must be greater than or equal to 0.", exception.getReason()); + assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); } } From 6659687b5006c813408776ae32ed78662eedf5ad Mon Sep 17 00:00:00 2001 From: Lukas Connolly Date: Sat, 8 Jun 2024 11:33:22 +0200 Subject: [PATCH 05/13] TEST: NAV-77 - Add same tests for get isolines. --- .../app/controller/RoutingControllerTest.java | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java b/src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java index 2c50ec1c..2f637809 100644 --- a/src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java +++ b/src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java @@ -1,6 +1,7 @@ package ch.naviqore.app.controller; import ch.naviqore.app.dto.Connection; +import ch.naviqore.app.dto.EarliestArrival; import ch.naviqore.service.PublicTransitService; import ch.naviqore.service.Stop; import ch.naviqore.service.exception.StopNotFoundException; @@ -186,4 +187,109 @@ void testGetConnections_InvalidMinTransferTime() { assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); } + @Test + void testGetIsoLines() { + // Arrange + String sourceStopId = "sourceStopId"; + LocalDateTime departureDateTime = LocalDateTime.now(); + + Stop sourceStop = mock(Stop.class); + + try { + when(publicTransitService.getStopById(sourceStopId)).thenReturn(sourceStop); + } catch (StopNotFoundException e) { + fail("StopNotFoundException was thrown", e); + } + when(publicTransitService.getIsolines(eq(sourceStop), eq(departureDateTime), any())).thenReturn( + Collections.emptyMap()); + + // Act + List connections = routingController.getIsolines(sourceStopId, -1.0, -1.0, departureDateTime, + 30, 2, 120, 5); + + // Assert + assertNotNull(connections); + } + + @Test + void testGetIsoLines_InvalidSourceStopId() { + // Arrange + String invalidStopId = "invalidStopId"; + + try { + when(publicTransitService.getStopById(invalidStopId)).thenThrow(new StopNotFoundException(invalidStopId)); + } catch (StopNotFoundException e) { + fail("StopNotFoundException was thrown", e); + } + + // Act & Assert + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + routingController.getIsolines(invalidStopId, -91.0, -181.0, LocalDateTime.now(), 30, 2, 120, 5); + }); + assertEquals("Stop not found", exception.getReason()); + assertEquals(HttpStatusCode.valueOf(404), exception.getStatusCode()); + } + + @Test + void testGetIsoLines_MissingSourceAndCoordinates() { + // Act & Assert + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + routingController.getIsolines(null, -91.0, -181.0, LocalDateTime.now(), 30, 2, 120, 5); + }); + assertEquals("Either sourceStopId or sourceLatitude and sourceLongitude must be provided.", + exception.getReason()); + assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); + } + + @Test + void testGetIsoLines_InvalidCoordinates() { + // Act & Assert + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + routingController.getIsolines(null, 91, 181, LocalDateTime.now(), 30, 2, 120, 5); + }); + assertEquals("Coordinates must be valid, Latitude between -90 and 90 and Longitude between -180 and 180.", + exception.getReason()); + assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); + } + + @Test + void testGetIsoLines_InvalidMaxTransferNumber() { + // Act & Assert + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + routingController.getIsolines(null, 0, 0, LocalDateTime.now(), 30, -2, 120, 5); + }); + assertEquals("Max transfer number must be greater than or equal to 0.", exception.getReason()); + assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); + } + + @Test + void testGetIsoLines_InvalidMaxWalkingDuration() { + // Act & Assert + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + routingController.getIsolines(null, 0, 0, LocalDateTime.now(), -30, 2, 120, 5); + }); + assertEquals("Max walking duration must be greater than or equal to 0.", exception.getReason()); + assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); + } + + @Test + void testGetIsoLines_InvalidMaxTravelTime() { + // Act & Assert + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + routingController.getIsolines(null, 0, 0, LocalDateTime.now(), 30, 2, -120, 5); + }); + assertEquals("Max travel time must be greater than 0.", exception.getReason()); + assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); + } + + @Test + void testGetIsoLines_InvalidMinTransferTime() { + // Act & Assert + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + routingController.getIsolines(null, 0, 0, LocalDateTime.now(), 30, 2, 120, -5); + }); + assertEquals("Min transfer time must be greater than or equal to 0.", exception.getReason()); + assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); + } + } From 57ad8c095237ac9f92795f58bd79f46142a37b92 Mon Sep 17 00:00:00 2001 From: Lukas Connolly Date: Sat, 8 Jun 2024 14:05:34 +0200 Subject: [PATCH 06/13] ENH: NAV-77 - Add coordinate validation for getNearestStops --- .../ch/naviqore/app/controller/ScheduleController.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/ch/naviqore/app/controller/ScheduleController.java b/src/main/java/ch/naviqore/app/controller/ScheduleController.java index d9b012aa..db0ad37e 100644 --- a/src/main/java/ch/naviqore/app/controller/ScheduleController.java +++ b/src/main/java/ch/naviqore/app/controller/ScheduleController.java @@ -50,7 +50,14 @@ public List getNearestStops(@RequestParam double latitude, @Requ throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Max distance can not be negative"); } - return service.getNearestStops(new GeoCoordinate(latitude, longitude), maxDistance, limit) + GeoCoordinate location; + try { + location = new GeoCoordinate(latitude, longitude); + } catch (IllegalArgumentException e) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.getMessage(), e); + } + + return service.getNearestStops(location, maxDistance, limit) .stream() .map(stop -> map(stop, latitude, longitude)) .toList(); From 90203bf837f185e16d4a6aafe841eb1b665928d9 Mon Sep 17 00:00:00 2001 From: Lukas Connolly Date: Sat, 8 Jun 2024 14:06:01 +0200 Subject: [PATCH 07/13] TEST: NAV--77 - Add tests for schedule controller in spring rest api --- .../controller/ScheduleControllerTest.java | 238 ++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 src/test/java/ch/naviqore/app/controller/ScheduleControllerTest.java diff --git a/src/test/java/ch/naviqore/app/controller/ScheduleControllerTest.java b/src/test/java/ch/naviqore/app/controller/ScheduleControllerTest.java new file mode 100644 index 00000000..0d1d6297 --- /dev/null +++ b/src/test/java/ch/naviqore/app/controller/ScheduleControllerTest.java @@ -0,0 +1,238 @@ +package ch.naviqore.app.controller; + +import ch.naviqore.app.dto.Departure; +import ch.naviqore.app.dto.DistanceToStop; +import ch.naviqore.app.dto.SearchType; +import ch.naviqore.app.dto.Stop; +import ch.naviqore.service.ScheduleInformationService; +import ch.naviqore.service.exception.StopNotFoundException; +import ch.naviqore.utils.spatial.GeoCoordinate; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.http.HttpStatusCode; +import org.springframework.web.server.ResponseStatusException; + +import java.time.LocalDateTime; +import java.util.List; + +import static ch.naviqore.app.dto.DtoMapper.map; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ScheduleControllerTest { + + @Mock + private ScheduleInformationService scheduleInformationService; + + @InjectMocks + private ScheduleController scheduleController; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + } + + @Test + void testGetAutoCompleteStops() { + String query = "query"; + when(scheduleInformationService.getStops(query, map(SearchType.STARTS_WITH))).thenReturn(List.of()); + List stops = scheduleController.getAutoCompleteStops(query, 10, SearchType.STARTS_WITH); + + assertNotNull(stops); + } + + @Test + void testGetAutoCompleteStops_withNegativeLimit() { + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + scheduleController.getAutoCompleteStops("query", -10, SearchType.STARTS_WITH); + }); + + assertEquals("Limit must be greater than 0", exception.getReason()); + assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); + } + + @Test + void testGetAutoCompleteStops_withZeroLimit() { + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + scheduleController.getAutoCompleteStops("query", 0, SearchType.STARTS_WITH); + }); + + assertEquals("Limit must be greater than 0", exception.getReason()); + assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); + } + + @Test + void testGetNearestStops() { + GeoCoordinate location = new GeoCoordinate(0, 0); + int radius = 1000; + int limit = 10; + + when(scheduleInformationService.getNearestStops(location, radius, limit)).thenReturn(List.of()); + + List stops = scheduleController.getNearestStops(location.latitude(), location.longitude(), + radius, limit); + + assertNotNull(stops); + } + + @Test + void testGetNearestStops_withNegativeLimit() { + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + scheduleController.getNearestStops(0, 0, 1000, -10); + }); + + assertEquals("Limit must be greater than 0", exception.getReason()); + assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); + } + + @Test + void testGetNearestStops_withZeroLimit() { + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + scheduleController.getNearestStops(0, 0, 1000, 0); + }); + + assertEquals("Limit must be greater than 0", exception.getReason()); + assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); + } + + @Test + void testGetNearestStops_withNegativeMaxDistance() { + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + scheduleController.getNearestStops(0, 0, -1000, 10); + }); + + assertEquals("Max distance can not be negative", exception.getReason()); + assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); + } + + @ParameterizedTest(name = "Test case {index}: Latitude={0}, Longitude={1}") + @CsvSource({ + "91, 0", // Invalid latitude + "-91, 0", // Invalid latitude + "0, 181", // Invalid longitude + "0, -181", // Invalid longitude + "91, 181", // Invalid latitude and longitude + "-91, -181" // Invalid latitude and longitude + }) + void testGetNearestStops_withInvalidCoordinates(double latitude, double longitude) { + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + scheduleController.getNearestStops(latitude, longitude, 1000, 10); + }); + assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); + } + + @Test + void testGetStop() throws StopNotFoundException { + String stopId = "stopId"; + ch.naviqore.service.Stop serviceStop = mock(ch.naviqore.service.Stop.class); + when(scheduleInformationService.getStopById(stopId)).thenReturn(serviceStop); + Stop stop = scheduleController.getStop(stopId); + assertNotNull(stop); + } + + @Test + void testGetStop_withStopNotFoundException() throws StopNotFoundException { + String stopId = "stopId"; + when(scheduleInformationService.getStopById(stopId)).thenThrow(StopNotFoundException.class); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + scheduleController.getStop(stopId); + }); + assertEquals(HttpStatusCode.valueOf(404), exception.getStatusCode()); + } + + @Test + void testGetDepartures() throws StopNotFoundException { + String stopId = "stopId"; + ch.naviqore.service.Stop serviceStop = mock(ch.naviqore.service.Stop.class); + when(scheduleInformationService.getStopById(stopId)).thenReturn(serviceStop); + List stopTimes = List.of(); + when(scheduleInformationService.getNextDepartures(serviceStop, null, null, 10)).thenReturn(stopTimes); + List stopTimeDtos = scheduleController.getDepartures(stopId, null, 10, null); + assertNotNull(stopTimeDtos); + } + + @Test + void testGetDepartures_withStopNotFoundException() throws StopNotFoundException { + String stopId = "stopId"; + when(scheduleInformationService.getStopById(stopId)).thenThrow(StopNotFoundException.class); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + scheduleController.getDepartures(stopId, null, 10, null); + }); + assertEquals(HttpStatusCode.valueOf(404), exception.getStatusCode()); + } + + @Test + void testGetDepartures_withUntilDateTimeBeforeDepartureDateTime() throws StopNotFoundException { + String stopId = "stopId"; + LocalDateTime departureTime = LocalDateTime.now(); + LocalDateTime untilTime = departureTime.minusMinutes(1); + + when(scheduleInformationService.getStopById(stopId)).thenReturn(mock(ch.naviqore.service.Stop.class)); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + scheduleController.getDepartures(stopId, departureTime, 10, untilTime); + }); + assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); + } + + @Test + void testGetDepartures_withNullDepartureDateTime() throws StopNotFoundException { + String stopId = "stopId"; + int limit = 10; + LocalDateTime untilTime = LocalDateTime.now().plusMinutes(1); + ch.naviqore.service.Stop serviceStop = mock(ch.naviqore.service.Stop.class); + when(scheduleInformationService.getStopById(stopId)).thenReturn(serviceStop); + List stopTimes = List.of(); + when(scheduleInformationService.getNextDepartures(eq(serviceStop), any(), eq(untilTime) + , eq(limit))).thenReturn(stopTimes); + List stopTimeDtos = scheduleController.getDepartures(stopId, null, limit, untilTime); + assertNotNull(stopTimeDtos); + } + + @Test + void testGetDepartures_withDepartureDateTime() throws StopNotFoundException { + String stopId = "stopId"; + int limit = 10; + LocalDateTime departureTime = LocalDateTime.now().plusDays(2); + LocalDateTime untilTime = departureTime.plusMinutes(1); + ch.naviqore.service.Stop serviceStop = mock(ch.naviqore.service.Stop.class); + when(scheduleInformationService.getStopById(stopId)).thenReturn(serviceStop); + List stopTimes = List.of(); + when(scheduleInformationService.getNextDepartures(eq(serviceStop), eq(departureTime), eq(untilTime) + , eq(limit))).thenReturn(stopTimes); + List stopTimeDtos = scheduleController.getDepartures(stopId, departureTime, limit, untilTime); + assertNotNull(stopTimeDtos); + } + + @Test + void testGetDepartures_withNullUntilDateTime() throws StopNotFoundException { + String stopId = "stopId"; + int limit = 10; + LocalDateTime departureTime = LocalDateTime.now().plusDays(2); + ch.naviqore.service.Stop serviceStop = mock(ch.naviqore.service.Stop.class); + when(scheduleInformationService.getStopById(stopId)).thenReturn(serviceStop); + List stopTimes = List.of(); + when(scheduleInformationService.getNextDepartures(eq(serviceStop), eq(departureTime), any() + , eq(limit))).thenReturn(stopTimes); + List stopTimeDtos = scheduleController.getDepartures(stopId, departureTime, limit, null); + assertNotNull(stopTimeDtos); + } + + @Test + void testGetDepartures_withInvalidLimit() { + int limit = 0; + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + scheduleController.getDepartures("stopId", null, limit, null); + }); + assertEquals("Limit must be greater than 0", exception.getReason()); + assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); + } + +} From a64f7ab17ec4fcfb6403a19eaab7b75323d45d76 Mon Sep 17 00:00:00 2001 From: Merlin Unterfinger Date: Mon, 10 Jun 2024 17:19:43 +0200 Subject: [PATCH 08/13] TEST: NAV-77 - Extract constants --- .../app/service/ServiceConfigParserIT.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/test/java/ch/naviqore/app/service/ServiceConfigParserIT.java b/src/test/java/ch/naviqore/app/service/ServiceConfigParserIT.java index fb9c620d..e37d3e9b 100644 --- a/src/test/java/ch/naviqore/app/service/ServiceConfigParserIT.java +++ b/src/test/java/ch/naviqore/app/service/ServiceConfigParserIT.java @@ -8,23 +8,23 @@ public class ServiceConfigParserIT { + private static final String GTFS_URL = "src/test/resources/ch/naviqore/gtfs/schedule/sample-feed-1.zip"; + private static final int MINIMUM_TRANSFER_TIME = 200; + private static final int MAXIMUM_WALKING_DISTANCE = 600; + private static final int WALKING_SPEED = 4000; + private static final String WALKING_CALCULATOR_TYPE = "BEE_LINE_DISTANCE"; + @Test void testServiceConfigParser_withValidInputs() { - String gtfsUrl = "src/test/resources/ch/naviqore/gtfs/schedule/sample-feed-1.zip"; - int minimumTransferTime = 200; - int maxWalkingDistance = 600; - int walkingSpeed = 4000; - String walkingCalculatorType = "BEE_LINE_DISTANCE"; - - ServiceConfigParser parser = new ServiceConfigParser(gtfsUrl, minimumTransferTime, maxWalkingDistance, - walkingSpeed, walkingCalculatorType); + ServiceConfigParser parser = new ServiceConfigParser(GTFS_URL, MINIMUM_TRANSFER_TIME, MAXIMUM_WALKING_DISTANCE, + WALKING_SPEED, WALKING_CALCULATOR_TYPE); // check that the service config has been loaded correctly ServiceConfig config = parser.getServiceConfig(); - assertEquals(gtfsUrl, config.getGtfsUrl()); - assertEquals(minimumTransferTime, config.getMinimumTransferTime()); - assertEquals(maxWalkingDistance, config.getMaxWalkingDistance()); - assertEquals(walkingSpeed, config.getWalkingSpeed()); + assertEquals(GTFS_URL, config.getGtfsUrl()); + assertEquals(MINIMUM_TRANSFER_TIME, config.getMinimumTransferTime()); + assertEquals(MAXIMUM_WALKING_DISTANCE, config.getMaxWalkingDistance()); + assertEquals(WALKING_SPEED, config.getWalkingSpeed()); assertEquals(ServiceConfig.WalkCalculatorType.BEE_LINE_DISTANCE, config.getWalkCalculatorType()); } @@ -32,8 +32,8 @@ void testServiceConfigParser_withValidInputs() { void testServiceConfigParser_withInvalidWalkCalculatorType() { // check that the service config has been loaded correctly assertThrows(IllegalArgumentException.class, - () -> new ServiceConfigParser("src/test/resources/ch/naviqore/gtfs/schedule/invalidSchedule.zip", 200, - 600, 4000, "INVALID")); + () -> new ServiceConfigParser(GTFS_URL, MINIMUM_TRANSFER_TIME, MAXIMUM_WALKING_DISTANCE, WALKING_SPEED, + "INVALID")); } } From 16a506988beec4ac6c06dfd22136951b9c7df63a Mon Sep 17 00:00:00 2001 From: Merlin Unterfinger Date: Mon, 10 Jun 2024 17:21:10 +0200 Subject: [PATCH 09/13] STYLE: NAV-77 - Format changes --- .../app/controller/RoutingController.java | 56 +++++++++---------- .../controller/ScheduleControllerTest.java | 15 +++-- 2 files changed, 35 insertions(+), 36 deletions(-) diff --git a/src/main/java/ch/naviqore/app/controller/RoutingController.java b/src/main/java/ch/naviqore/app/controller/RoutingController.java index cfae96e8..423c040c 100644 --- a/src/main/java/ch/naviqore/app/controller/RoutingController.java +++ b/src/main/java/ch/naviqore/app/controller/RoutingController.java @@ -35,6 +35,34 @@ public RoutingController(PublicTransitService service) { this.service = service; } + private static GeoCoordinate validateCoordinate(double latitude, double longitude) { + try { + return new GeoCoordinate(latitude, longitude); + } catch (IllegalArgumentException e) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, + "Coordinates must be valid, Latitude between -90 and 90 and Longitude between -180 and 180."); + } + } + + private static void validateQueryParams(int maxWalkingDuration, int maxTransferNumber, int maxTravelTime, + int minTransferTime) { + if (maxWalkingDuration < 0) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, + "Max walking duration must be greater than or equal to 0."); + } + if (maxTransferNumber < 0) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, + "Max transfer number must be greater than or equal to 0."); + } + if (maxTravelTime <= 0) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Max travel time must be greater than 0."); + } + if (minTransferTime < 0) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, + "Min transfer time must be greater than or equal to 0."); + } + } + @GetMapping("/connections") public List getConnections(@RequestParam(required = false) String sourceStopId, @RequestParam(required = false, defaultValue = "-91.0") double sourceLatitude, @@ -147,32 +175,4 @@ private ch.naviqore.service.Stop getStop(String stopId) { } } - private static GeoCoordinate validateCoordinate(double latitude, double longitude) { - try { - return new GeoCoordinate(latitude, longitude); - } catch (IllegalArgumentException e) { - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, - "Coordinates must be valid, Latitude between -90 and 90 and Longitude between -180 and 180."); - } - } - - private static void validateQueryParams(int maxWalkingDuration, int maxTransferNumber, int maxTravelTime, - int minTransferTime) { - if (maxWalkingDuration < 0) { - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, - "Max walking duration must be greater than or equal to 0."); - } - if (maxTransferNumber < 0) { - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, - "Max transfer number must be greater than or equal to 0."); - } - if (maxTravelTime <= 0) { - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Max travel time must be greater than 0."); - } - if (minTransferTime < 0) { - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, - "Min transfer time must be greater than or equal to 0."); - } - } - } diff --git a/src/test/java/ch/naviqore/app/controller/ScheduleControllerTest.java b/src/test/java/ch/naviqore/app/controller/ScheduleControllerTest.java index 0d1d6297..652ebf15 100644 --- a/src/test/java/ch/naviqore/app/controller/ScheduleControllerTest.java +++ b/src/test/java/ch/naviqore/app/controller/ScheduleControllerTest.java @@ -114,8 +114,7 @@ void testGetNearestStops_withNegativeMaxDistance() { } @ParameterizedTest(name = "Test case {index}: Latitude={0}, Longitude={1}") - @CsvSource({ - "91, 0", // Invalid latitude + @CsvSource({"91, 0", // Invalid latitude "-91, 0", // Invalid latitude "0, 181", // Invalid longitude "0, -181", // Invalid longitude @@ -190,8 +189,8 @@ void testGetDepartures_withNullDepartureDateTime() throws StopNotFoundException ch.naviqore.service.Stop serviceStop = mock(ch.naviqore.service.Stop.class); when(scheduleInformationService.getStopById(stopId)).thenReturn(serviceStop); List stopTimes = List.of(); - when(scheduleInformationService.getNextDepartures(eq(serviceStop), any(), eq(untilTime) - , eq(limit))).thenReturn(stopTimes); + when(scheduleInformationService.getNextDepartures(eq(serviceStop), any(), eq(untilTime), eq(limit))).thenReturn( + stopTimes); List stopTimeDtos = scheduleController.getDepartures(stopId, null, limit, untilTime); assertNotNull(stopTimeDtos); } @@ -205,8 +204,8 @@ void testGetDepartures_withDepartureDateTime() throws StopNotFoundException { ch.naviqore.service.Stop serviceStop = mock(ch.naviqore.service.Stop.class); when(scheduleInformationService.getStopById(stopId)).thenReturn(serviceStop); List stopTimes = List.of(); - when(scheduleInformationService.getNextDepartures(eq(serviceStop), eq(departureTime), eq(untilTime) - , eq(limit))).thenReturn(stopTimes); + when(scheduleInformationService.getNextDepartures(eq(serviceStop), eq(departureTime), eq(untilTime), + eq(limit))).thenReturn(stopTimes); List stopTimeDtos = scheduleController.getDepartures(stopId, departureTime, limit, untilTime); assertNotNull(stopTimeDtos); } @@ -219,8 +218,8 @@ void testGetDepartures_withNullUntilDateTime() throws StopNotFoundException { ch.naviqore.service.Stop serviceStop = mock(ch.naviqore.service.Stop.class); when(scheduleInformationService.getStopById(stopId)).thenReturn(serviceStop); List stopTimes = List.of(); - when(scheduleInformationService.getNextDepartures(eq(serviceStop), eq(departureTime), any() - , eq(limit))).thenReturn(stopTimes); + when(scheduleInformationService.getNextDepartures(eq(serviceStop), eq(departureTime), any(), + eq(limit))).thenReturn(stopTimes); List stopTimeDtos = scheduleController.getDepartures(stopId, departureTime, limit, null); assertNotNull(stopTimeDtos); } From dd3b08b32fb51da938bc5c121de06032030eab06 Mon Sep 17 00:00:00 2001 From: Merlin Unterfinger Date: Mon, 10 Jun 2024 17:22:06 +0200 Subject: [PATCH 10/13] ORG: NAV-77 - Remove example tests, since we now use mockito in our tests --- .../java/ch/naviqore/example/Container.java | 15 ------- src/main/java/ch/naviqore/example/Dummy.java | 20 ---------- .../java/ch/naviqore/example/DummyIT.java | 31 --------------- .../java/ch/naviqore/example/DummyTest.java | 39 ------------------- 4 files changed, 105 deletions(-) delete mode 100644 src/main/java/ch/naviqore/example/Container.java delete mode 100644 src/main/java/ch/naviqore/example/Dummy.java delete mode 100644 src/test/java/ch/naviqore/example/DummyIT.java delete mode 100644 src/test/java/ch/naviqore/example/DummyTest.java diff --git a/src/main/java/ch/naviqore/example/Container.java b/src/main/java/ch/naviqore/example/Container.java deleted file mode 100644 index 8fdf70b9..00000000 --- a/src/main/java/ch/naviqore/example/Container.java +++ /dev/null @@ -1,15 +0,0 @@ -package ch.naviqore.example; - -import lombok.Getter; -import lombok.Setter; - -/** - * Container class to illustrate mocking - * - * @author munterfi - */ -@Getter -@Setter -public class Container { - private int value = 0; -} diff --git a/src/main/java/ch/naviqore/example/Dummy.java b/src/main/java/ch/naviqore/example/Dummy.java deleted file mode 100644 index bb95f750..00000000 --- a/src/main/java/ch/naviqore/example/Dummy.java +++ /dev/null @@ -1,20 +0,0 @@ -package ch.naviqore.example; - -import lombok.RequiredArgsConstructor; - -/** - * Dummy class - * - * @author munterfi - */ -@RequiredArgsConstructor -public class Dummy { - - private final Container container; - - public int add(int a) { - int newValue = container.getValue() + a; - container.setValue(newValue); - return newValue; - } -} diff --git a/src/test/java/ch/naviqore/example/DummyIT.java b/src/test/java/ch/naviqore/example/DummyIT.java deleted file mode 100644 index 21cf1535..00000000 --- a/src/test/java/ch/naviqore/example/DummyIT.java +++ /dev/null @@ -1,31 +0,0 @@ -package ch.naviqore.example; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Dummy integration test - * - * @author munterfi - */ -class DummyIT { - - private Container container; - private Dummy dummy; - - @BeforeEach - void setUp() { - container = new Container(); - dummy = new Dummy(container); - } - - @Test - void add() { - int initial = container.getValue(); - int result = dummy.add(10); - - assertThat(result).isEqualTo(initial + 10); - } -} \ No newline at end of file diff --git a/src/test/java/ch/naviqore/example/DummyTest.java b/src/test/java/ch/naviqore/example/DummyTest.java deleted file mode 100644 index 4d9ef7d0..00000000 --- a/src/test/java/ch/naviqore/example/DummyTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package ch.naviqore.example; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.*; - -/** - * Dummy unit test - * - * @author munterfi - */ -@ExtendWith(MockitoExtension.class) -class DummyTest { - - @Mock - private Container container; - - @InjectMocks - private Dummy dummy; - - @Test - void add() { - // mock getter of container - when(container.getValue()).thenReturn(10); - - // act - int result = dummy.add(5); - - // verify container.setValue(15) is called - verify(container, times(1)).getValue(); - verify(container, times(1)).setValue(15); - assertThat(result).isEqualTo(15); - } -} \ No newline at end of file From a082ebcf8eeefef7ed8da7874b8274f6b4f35b5d Mon Sep 17 00:00:00 2001 From: Merlin Unterfinger Date: Mon, 10 Jun 2024 17:49:59 +0200 Subject: [PATCH 11/13] TEST: NAV-77 - Open mocks using annotations, since it provides better validation by mockito - Resolve UnnecessaryStubbingException, uncalled stubs. - Just throw exceptions directly if they occur, no need to catch them and fail again. --- .../app/controller/RoutingControllerTest.java | 55 +++++-------------- 1 file changed, 15 insertions(+), 40 deletions(-) diff --git a/src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java b/src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java index 2f637809..a434c176 100644 --- a/src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java +++ b/src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java @@ -6,11 +6,11 @@ import ch.naviqore.service.Stop; import ch.naviqore.service.exception.StopNotFoundException; import ch.naviqore.utils.spatial.GeoCoordinate; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.http.HttpStatusCode; import org.springframework.web.server.ResponseStatusException; @@ -24,6 +24,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +@ExtendWith(MockitoExtension.class) public class RoutingControllerTest { @Mock @@ -32,13 +33,8 @@ public class RoutingControllerTest { @InjectMocks private RoutingController routingController; - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - } - @Test - void testGetConnections_WithValidSourceAndTargetStopIds() { + void testGetConnections_WithValidSourceAndTargetStopIds() throws StopNotFoundException { // Arrange String sourceStopId = "sourceStopId"; String targetStopId = "targetStopId"; @@ -47,12 +43,8 @@ void testGetConnections_WithValidSourceAndTargetStopIds() { Stop sourceStop = mock(Stop.class); Stop targetStop = mock(Stop.class); - try { - when(publicTransitService.getStopById(sourceStopId)).thenReturn(sourceStop); - when(publicTransitService.getStopById(targetStopId)).thenReturn(targetStop); - } catch (StopNotFoundException e) { - fail("StopNotFoundException was thrown", e); - } + when(publicTransitService.getStopById(sourceStopId)).thenReturn(sourceStop); + when(publicTransitService.getStopById(targetStopId)).thenReturn(targetStop); when(publicTransitService.getConnections(eq(sourceStop), eq(targetStop), any(), any(), any())).thenReturn( Collections.emptyList()); @@ -65,7 +57,7 @@ void testGetConnections_WithValidSourceAndTargetStopIds() { } @Test - void testGetConnections_WithoutSourceStopIdButWithCoordinates() { + void testGetConnections_WithoutSourceStopIdButWithCoordinates() throws StopNotFoundException { // Arrange double sourceLatitude = 46.2044; double sourceLongitude = 6.1432; @@ -74,11 +66,7 @@ void testGetConnections_WithoutSourceStopIdButWithCoordinates() { Stop targetStop = mock(Stop.class); - try { - when(publicTransitService.getStopById(targetStopId)).thenReturn(targetStop); - } catch (StopNotFoundException e) { - fail("StopNotFoundException was thrown", e); - } + when(publicTransitService.getStopById(targetStopId)).thenReturn(targetStop); when(publicTransitService.getConnections(any(GeoCoordinate.class), eq(targetStop), any(), any(), any())).thenReturn(Collections.emptyList()); @@ -91,18 +79,14 @@ void testGetConnections_WithoutSourceStopIdButWithCoordinates() { } @Test - void testGetConnections_InvalidStopId() { + void testGetConnections_InvalidStopId() throws StopNotFoundException { // Arrange String invalidStopId = "invalidStopId"; String targetStopId = "targetStopId"; Stop targetStop = mock(Stop.class); - try { - when(publicTransitService.getStopById(invalidStopId)).thenThrow(new StopNotFoundException(invalidStopId)); - when(publicTransitService.getStopById(targetStopId)).thenReturn(targetStop); - } catch (StopNotFoundException e) { - fail("StopNotFoundException was thrown", e); - } + when(publicTransitService.getStopById(invalidStopId)).thenThrow(new StopNotFoundException(invalidStopId)); + // Act & Assert ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { routingController.getConnections(invalidStopId, -91.0, -181.0, targetStopId, -91.0, -181.0, @@ -188,18 +172,14 @@ void testGetConnections_InvalidMinTransferTime() { } @Test - void testGetIsoLines() { + void testGetIsoLines() throws StopNotFoundException { // Arrange String sourceStopId = "sourceStopId"; LocalDateTime departureDateTime = LocalDateTime.now(); Stop sourceStop = mock(Stop.class); - try { - when(publicTransitService.getStopById(sourceStopId)).thenReturn(sourceStop); - } catch (StopNotFoundException e) { - fail("StopNotFoundException was thrown", e); - } + when(publicTransitService.getStopById(sourceStopId)).thenReturn(sourceStop); when(publicTransitService.getIsolines(eq(sourceStop), eq(departureDateTime), any())).thenReturn( Collections.emptyMap()); @@ -212,15 +192,10 @@ void testGetIsoLines() { } @Test - void testGetIsoLines_InvalidSourceStopId() { + void testGetIsoLines_InvalidSourceStopId() throws StopNotFoundException { // Arrange String invalidStopId = "invalidStopId"; - - try { - when(publicTransitService.getStopById(invalidStopId)).thenThrow(new StopNotFoundException(invalidStopId)); - } catch (StopNotFoundException e) { - fail("StopNotFoundException was thrown", e); - } + when(publicTransitService.getStopById(invalidStopId)).thenThrow(new StopNotFoundException(invalidStopId)); // Act & Assert ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { From 3a4f75329ac60dfff99188f9c4907d330e556d51 Mon Sep 17 00:00:00 2001 From: Merlin Unterfinger Date: Mon, 10 Jun 2024 17:54:33 +0200 Subject: [PATCH 12/13] TEST: NAV-77 - Lambda expressions instead of statements - Open mocks using annotations also in RoutingControllerTest. - Again resolve UnnecessaryStubbingException, uncalled stubs. - Resolve PotentialStubbingProblem. --- .../app/controller/RoutingControllerTest.java | 83 ++++++++----------- .../controller/ScheduleControllerTest.java | 66 ++++++--------- 2 files changed, 60 insertions(+), 89 deletions(-) diff --git a/src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java b/src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java index a434c176..2455071f 100644 --- a/src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java +++ b/src/test/java/ch/naviqore/app/controller/RoutingControllerTest.java @@ -83,15 +83,13 @@ void testGetConnections_InvalidStopId() throws StopNotFoundException { // Arrange String invalidStopId = "invalidStopId"; String targetStopId = "targetStopId"; - Stop targetStop = mock(Stop.class); when(publicTransitService.getStopById(invalidStopId)).thenThrow(new StopNotFoundException(invalidStopId)); // Act & Assert - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - routingController.getConnections(invalidStopId, -91.0, -181.0, targetStopId, -91.0, -181.0, - LocalDateTime.now(), 30, 2, 120, 5); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> routingController.getConnections(invalidStopId, -91.0, -181.0, targetStopId, -91.0, -181.0, + LocalDateTime.now(), 30, 2, 120, 5)); assertEquals("Stop not found", exception.getReason()); assertEquals(HttpStatusCode.valueOf(404), exception.getStatusCode()); } @@ -99,10 +97,9 @@ void testGetConnections_InvalidStopId() throws StopNotFoundException { @Test void testGetConnections_MissingSourceAndCoordinates() { // Act & Assert - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - routingController.getConnections(null, -91.0, -181.0, "targetStopId", -91.0, -181.0, LocalDateTime.now(), - 30, 2, 120, 5); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> routingController.getConnections(null, -91.0, -181.0, "targetStopId", -91.0, -181.0, + LocalDateTime.now(), 30, 2, 120, 5)); assertEquals("Either sourceStopId or sourceLatitude and sourceLongitude must be provided.", exception.getReason()); assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); @@ -111,10 +108,9 @@ void testGetConnections_MissingSourceAndCoordinates() { @Test void testGetConnections_MissingTargetAndCoordinates() { // Act & Assert - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - routingController.getConnections("sourceStopId", -91.0, -181.0, null, -91.0, -181.0, LocalDateTime.now(), - 30, 2, 120, 5); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> routingController.getConnections("sourceStopId", -91.0, -181.0, null, -91.0, -181.0, + LocalDateTime.now(), 30, 2, 120, 5)); assertEquals("Either targetStopId or targetLatitude and targetLongitude must be provided.", exception.getReason()); assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); @@ -123,9 +119,9 @@ void testGetConnections_MissingTargetAndCoordinates() { @Test void testGetConnection_InvalidCoordinates() { // Act & Assert - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - routingController.getConnections(null, 91, 181, null, 32, 32, LocalDateTime.now(), 30, 2, 120, 5); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> routingController.getConnections(null, 91, 181, null, 32, 32, LocalDateTime.now(), 30, 2, 120, + 5)); assertEquals("Coordinates must be valid, Latitude between -90 and 90 and Longitude between -180 and 180.", exception.getReason()); assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); @@ -134,9 +130,8 @@ void testGetConnection_InvalidCoordinates() { @Test void testGetConnections_InvalidMaxTransferNumber() { // Act & Assert - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - routingController.getConnections(null, 0, 0, null, 0, 0, LocalDateTime.now(), 30, -2, 120, 5); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> routingController.getConnections(null, 0, 0, null, 0, 0, LocalDateTime.now(), 30, -2, 120, 5)); assertEquals("Max transfer number must be greater than or equal to 0.", exception.getReason()); assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); } @@ -144,9 +139,8 @@ void testGetConnections_InvalidMaxTransferNumber() { @Test void testGetConnections_InvalidMaxWalkingDuration() { // Act & Assert - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - routingController.getConnections(null, 0, 0, null, 0, 0, LocalDateTime.now(), -30, 2, 120, 5); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> routingController.getConnections(null, 0, 0, null, 0, 0, LocalDateTime.now(), -30, 2, 120, 5)); assertEquals("Max walking duration must be greater than or equal to 0.", exception.getReason()); assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); } @@ -154,9 +148,8 @@ void testGetConnections_InvalidMaxWalkingDuration() { @Test void testGetConnections_InvalidMaxTravelTime() { // Act & Assert - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - routingController.getConnections(null, 0, 0, null, 0, 0, LocalDateTime.now(), 30, 2, -120, 5); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> routingController.getConnections(null, 0, 0, null, 0, 0, LocalDateTime.now(), 30, 2, -120, 5)); assertEquals("Max travel time must be greater than 0.", exception.getReason()); assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); } @@ -164,9 +157,8 @@ void testGetConnections_InvalidMaxTravelTime() { @Test void testGetConnections_InvalidMinTransferTime() { // Act & Assert - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - routingController.getConnections(null, 0, 0, null, 0, 0, LocalDateTime.now(), 30, 2, 120, -5); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> routingController.getConnections(null, 0, 0, null, 0, 0, LocalDateTime.now(), 30, 2, 120, -5)); assertEquals("Min transfer time must be greater than or equal to 0.", exception.getReason()); assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); } @@ -198,9 +190,8 @@ void testGetIsoLines_InvalidSourceStopId() throws StopNotFoundException { when(publicTransitService.getStopById(invalidStopId)).thenThrow(new StopNotFoundException(invalidStopId)); // Act & Assert - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - routingController.getIsolines(invalidStopId, -91.0, -181.0, LocalDateTime.now(), 30, 2, 120, 5); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> routingController.getIsolines(invalidStopId, -91.0, -181.0, LocalDateTime.now(), 30, 2, 120, 5)); assertEquals("Stop not found", exception.getReason()); assertEquals(HttpStatusCode.valueOf(404), exception.getStatusCode()); } @@ -208,9 +199,8 @@ void testGetIsoLines_InvalidSourceStopId() throws StopNotFoundException { @Test void testGetIsoLines_MissingSourceAndCoordinates() { // Act & Assert - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - routingController.getIsolines(null, -91.0, -181.0, LocalDateTime.now(), 30, 2, 120, 5); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> routingController.getIsolines(null, -91.0, -181.0, LocalDateTime.now(), 30, 2, 120, 5)); assertEquals("Either sourceStopId or sourceLatitude and sourceLongitude must be provided.", exception.getReason()); assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); @@ -219,9 +209,8 @@ void testGetIsoLines_MissingSourceAndCoordinates() { @Test void testGetIsoLines_InvalidCoordinates() { // Act & Assert - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - routingController.getIsolines(null, 91, 181, LocalDateTime.now(), 30, 2, 120, 5); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> routingController.getIsolines(null, 91, 181, LocalDateTime.now(), 30, 2, 120, 5)); assertEquals("Coordinates must be valid, Latitude between -90 and 90 and Longitude between -180 and 180.", exception.getReason()); assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); @@ -230,9 +219,8 @@ void testGetIsoLines_InvalidCoordinates() { @Test void testGetIsoLines_InvalidMaxTransferNumber() { // Act & Assert - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - routingController.getIsolines(null, 0, 0, LocalDateTime.now(), 30, -2, 120, 5); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> routingController.getIsolines(null, 0, 0, LocalDateTime.now(), 30, -2, 120, 5)); assertEquals("Max transfer number must be greater than or equal to 0.", exception.getReason()); assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); } @@ -240,9 +228,8 @@ void testGetIsoLines_InvalidMaxTransferNumber() { @Test void testGetIsoLines_InvalidMaxWalkingDuration() { // Act & Assert - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - routingController.getIsolines(null, 0, 0, LocalDateTime.now(), -30, 2, 120, 5); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> routingController.getIsolines(null, 0, 0, LocalDateTime.now(), -30, 2, 120, 5)); assertEquals("Max walking duration must be greater than or equal to 0.", exception.getReason()); assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); } @@ -250,9 +237,8 @@ void testGetIsoLines_InvalidMaxWalkingDuration() { @Test void testGetIsoLines_InvalidMaxTravelTime() { // Act & Assert - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - routingController.getIsolines(null, 0, 0, LocalDateTime.now(), 30, 2, -120, 5); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> routingController.getIsolines(null, 0, 0, LocalDateTime.now(), 30, 2, -120, 5)); assertEquals("Max travel time must be greater than 0.", exception.getReason()); assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); } @@ -260,9 +246,8 @@ void testGetIsoLines_InvalidMaxTravelTime() { @Test void testGetIsoLines_InvalidMinTransferTime() { // Act & Assert - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - routingController.getIsolines(null, 0, 0, LocalDateTime.now(), 30, 2, 120, -5); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> routingController.getIsolines(null, 0, 0, LocalDateTime.now(), 30, 2, 120, -5)); assertEquals("Min transfer time must be greater than or equal to 0.", exception.getReason()); assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); } diff --git a/src/test/java/ch/naviqore/app/controller/ScheduleControllerTest.java b/src/test/java/ch/naviqore/app/controller/ScheduleControllerTest.java index 652ebf15..f5680ae2 100644 --- a/src/test/java/ch/naviqore/app/controller/ScheduleControllerTest.java +++ b/src/test/java/ch/naviqore/app/controller/ScheduleControllerTest.java @@ -7,13 +7,13 @@ import ch.naviqore.service.ScheduleInformationService; import ch.naviqore.service.exception.StopNotFoundException; import ch.naviqore.utils.spatial.GeoCoordinate; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.http.HttpStatusCode; import org.springframework.web.server.ResponseStatusException; @@ -27,6 +27,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +@ExtendWith(MockitoExtension.class) public class ScheduleControllerTest { @Mock @@ -35,11 +36,6 @@ public class ScheduleControllerTest { @InjectMocks private ScheduleController scheduleController; - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - } - @Test void testGetAutoCompleteStops() { String query = "query"; @@ -51,9 +47,8 @@ void testGetAutoCompleteStops() { @Test void testGetAutoCompleteStops_withNegativeLimit() { - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - scheduleController.getAutoCompleteStops("query", -10, SearchType.STARTS_WITH); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> scheduleController.getAutoCompleteStops("query", -10, SearchType.STARTS_WITH)); assertEquals("Limit must be greater than 0", exception.getReason()); assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); @@ -61,9 +56,8 @@ void testGetAutoCompleteStops_withNegativeLimit() { @Test void testGetAutoCompleteStops_withZeroLimit() { - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - scheduleController.getAutoCompleteStops("query", 0, SearchType.STARTS_WITH); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> scheduleController.getAutoCompleteStops("query", 0, SearchType.STARTS_WITH)); assertEquals("Limit must be greater than 0", exception.getReason()); assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); @@ -85,9 +79,8 @@ void testGetNearestStops() { @Test void testGetNearestStops_withNegativeLimit() { - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - scheduleController.getNearestStops(0, 0, 1000, -10); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> scheduleController.getNearestStops(0, 0, 1000, -10)); assertEquals("Limit must be greater than 0", exception.getReason()); assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); @@ -95,9 +88,8 @@ void testGetNearestStops_withNegativeLimit() { @Test void testGetNearestStops_withZeroLimit() { - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - scheduleController.getNearestStops(0, 0, 1000, 0); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> scheduleController.getNearestStops(0, 0, 1000, 0)); assertEquals("Limit must be greater than 0", exception.getReason()); assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); @@ -105,9 +97,8 @@ void testGetNearestStops_withZeroLimit() { @Test void testGetNearestStops_withNegativeMaxDistance() { - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - scheduleController.getNearestStops(0, 0, -1000, 10); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> scheduleController.getNearestStops(0, 0, -1000, 10)); assertEquals("Max distance can not be negative", exception.getReason()); assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); @@ -122,9 +113,8 @@ void testGetNearestStops_withNegativeMaxDistance() { "-91, -181" // Invalid latitude and longitude }) void testGetNearestStops_withInvalidCoordinates(double latitude, double longitude) { - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - scheduleController.getNearestStops(latitude, longitude, 1000, 10); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> scheduleController.getNearestStops(latitude, longitude, 1000, 10)); assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); } @@ -141,9 +131,8 @@ void testGetStop() throws StopNotFoundException { void testGetStop_withStopNotFoundException() throws StopNotFoundException { String stopId = "stopId"; when(scheduleInformationService.getStopById(stopId)).thenThrow(StopNotFoundException.class); - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - scheduleController.getStop(stopId); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> scheduleController.getStop(stopId)); assertEquals(HttpStatusCode.valueOf(404), exception.getStatusCode()); } @@ -153,7 +142,8 @@ void testGetDepartures() throws StopNotFoundException { ch.naviqore.service.Stop serviceStop = mock(ch.naviqore.service.Stop.class); when(scheduleInformationService.getStopById(stopId)).thenReturn(serviceStop); List stopTimes = List.of(); - when(scheduleInformationService.getNextDepartures(serviceStop, null, null, 10)).thenReturn(stopTimes); + when(scheduleInformationService.getNextDepartures(eq(serviceStop), any(LocalDateTime.class), eq(null), + eq(10))).thenReturn(stopTimes); List stopTimeDtos = scheduleController.getDepartures(stopId, null, 10, null); assertNotNull(stopTimeDtos); } @@ -162,22 +152,19 @@ void testGetDepartures() throws StopNotFoundException { void testGetDepartures_withStopNotFoundException() throws StopNotFoundException { String stopId = "stopId"; when(scheduleInformationService.getStopById(stopId)).thenThrow(StopNotFoundException.class); - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - scheduleController.getDepartures(stopId, null, 10, null); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> scheduleController.getDepartures(stopId, null, 10, null)); assertEquals(HttpStatusCode.valueOf(404), exception.getStatusCode()); } @Test - void testGetDepartures_withUntilDateTimeBeforeDepartureDateTime() throws StopNotFoundException { + void testGetDepartures_withUntilDateTimeBeforeDepartureDateTime() { String stopId = "stopId"; LocalDateTime departureTime = LocalDateTime.now(); LocalDateTime untilTime = departureTime.minusMinutes(1); - when(scheduleInformationService.getStopById(stopId)).thenReturn(mock(ch.naviqore.service.Stop.class)); - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - scheduleController.getDepartures(stopId, departureTime, 10, untilTime); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> scheduleController.getDepartures(stopId, departureTime, 10, untilTime)); assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); } @@ -227,9 +214,8 @@ void testGetDepartures_withNullUntilDateTime() throws StopNotFoundException { @Test void testGetDepartures_withInvalidLimit() { int limit = 0; - ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { - scheduleController.getDepartures("stopId", null, limit, null); - }); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, + () -> scheduleController.getDepartures("stopId", null, limit, null)); assertEquals("Limit must be greater than 0", exception.getReason()); assertEquals(HttpStatusCode.valueOf(400), exception.getStatusCode()); } From 50fe527fa1f8469574943adde8bf446360b38f84 Mon Sep 17 00:00:00 2001 From: Lukas Connolly Date: Mon, 10 Jun 2024 19:18:50 +0200 Subject: [PATCH 13/13] TEST: NAV-77 - Fix build issues with ServiceConfigParserIT and add more tests for config validation. --- .../app/service/ServiceConfigParserIT.java | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/test/java/ch/naviqore/app/service/ServiceConfigParserIT.java b/src/test/java/ch/naviqore/app/service/ServiceConfigParserIT.java index e37d3e9b..fb9d9a66 100644 --- a/src/test/java/ch/naviqore/app/service/ServiceConfigParserIT.java +++ b/src/test/java/ch/naviqore/app/service/ServiceConfigParserIT.java @@ -2,6 +2,11 @@ import ch.naviqore.service.config.ServiceConfig; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -10,14 +15,30 @@ public class ServiceConfigParserIT { private static final String GTFS_URL = "src/test/resources/ch/naviqore/gtfs/schedule/sample-feed-1.zip"; private static final int MINIMUM_TRANSFER_TIME = 200; + private static final int SAME_STATION_TRANSFER_TIME = 200; private static final int MAXIMUM_WALKING_DISTANCE = 600; private static final int WALKING_SPEED = 4000; private static final String WALKING_CALCULATOR_TYPE = "BEE_LINE_DISTANCE"; + static Stream provideTestCombinations() { + return Stream.of(Arguments.of(-1, SAME_STATION_TRANSFER_TIME, MAXIMUM_WALKING_DISTANCE, WALKING_SPEED, + WALKING_CALCULATOR_TYPE, "Minimum Transfer Time cannot be smaller zero."), + Arguments.of(MINIMUM_TRANSFER_TIME, -1, MAXIMUM_WALKING_DISTANCE, WALKING_SPEED, + WALKING_CALCULATOR_TYPE, "Same Station Transfer Time cannot be smaller zero."), + Arguments.of(MINIMUM_TRANSFER_TIME, SAME_STATION_TRANSFER_TIME, -1, WALKING_SPEED, + WALKING_CALCULATOR_TYPE, "Maximum Walking Distance cannot be smaller zero."), + Arguments.of(MINIMUM_TRANSFER_TIME, SAME_STATION_TRANSFER_TIME, MAXIMUM_WALKING_DISTANCE, -1, + WALKING_CALCULATOR_TYPE, "Walking speed cannot be smaller zero."), + Arguments.of(MINIMUM_TRANSFER_TIME, SAME_STATION_TRANSFER_TIME, MAXIMUM_WALKING_DISTANCE, 0, + WALKING_CALCULATOR_TYPE, "Walking speed cannot be zero."), + Arguments.of(MINIMUM_TRANSFER_TIME, SAME_STATION_TRANSFER_TIME, MAXIMUM_WALKING_DISTANCE, WALKING_SPEED, + "INVALID", "Can't process invalid Walking Calculator Type.")); + } + @Test void testServiceConfigParser_withValidInputs() { - ServiceConfigParser parser = new ServiceConfigParser(GTFS_URL, MINIMUM_TRANSFER_TIME, MAXIMUM_WALKING_DISTANCE, - WALKING_SPEED, WALKING_CALCULATOR_TYPE); + ServiceConfigParser parser = new ServiceConfigParser(GTFS_URL, MINIMUM_TRANSFER_TIME, + SAME_STATION_TRANSFER_TIME, MAXIMUM_WALKING_DISTANCE, WALKING_SPEED, WALKING_CALCULATOR_TYPE); // check that the service config has been loaded correctly ServiceConfig config = parser.getServiceConfig(); @@ -32,8 +53,19 @@ void testServiceConfigParser_withValidInputs() { void testServiceConfigParser_withInvalidWalkCalculatorType() { // check that the service config has been loaded correctly assertThrows(IllegalArgumentException.class, - () -> new ServiceConfigParser(GTFS_URL, MINIMUM_TRANSFER_TIME, MAXIMUM_WALKING_DISTANCE, WALKING_SPEED, - "INVALID")); + () -> new ServiceConfigParser(GTFS_URL, MINIMUM_TRANSFER_TIME, SAME_STATION_TRANSFER_TIME, + MAXIMUM_WALKING_DISTANCE, WALKING_SPEED, "INVALID")); + } + + @ParameterizedTest(name = "{5}") + @MethodSource("provideTestCombinations") + void testServiceConfigParser_withInvalidInputs(int minimumTransferTime, int sameStationTransferTime, + int maxWalkingDistance, int walkingSpeed, + String walkingCalculatorType, String message) { + // check that the service config has been loaded correctly + assertThrows(IllegalArgumentException.class, + () -> new ServiceConfigParser(GTFS_URL, minimumTransferTime, sameStationTransferTime, + maxWalkingDistance, walkingSpeed, walkingCalculatorType), message); } }