Browse Source

JUnit for all infrastructure endpoints

Lukas Cerny 1 year ago
parent
commit
59692b7280

+ 4 - 4
src/main/java/cz/senslog/telemetry/server/ws/OpenAPIHandler.java

@@ -653,7 +653,7 @@ public class OpenAPIHandler {
                         data.stream().map(u -> (navigationLinks ? JsonObject.of(
                                 "Unit@NavigationLink", String.format("%s/units/%d", host, u.getUnitId())
                         ) : JsonObject.of()).mergeIn(JsonObject.of(
-                                "id", u.getUnitId(),
+                                "unitId", u.getUnitId(),
                                 "name", u.getName(),
                                 "description", u.getDescription()
                         ))).collect(toList())).encode()))
@@ -1247,7 +1247,7 @@ public class OpenAPIHandler {
                         ) : JsonObject.of()).mergeIn(JsonObject.of(
                                 "id", e.getId(),
                                 "fromTime", DATE_TIME_FORMATTER.apply(e.getFromTime(), zone),
-                                "description", DATE_TIME_FORMATTER.apply(e.getToTime(), zone)
+                                "toTime", DATE_TIME_FORMATTER.apply(e.getToTime(), zone)
                         ))).collect(toList())).encode()))
                 .onFailure(rc::fail);
     }
@@ -1268,7 +1268,7 @@ public class OpenAPIHandler {
                                 "self@NavigationLink", String.format("%s/events/%d", host, e.getId()),
                                 "Driver@NavigationLink", String.format("%s/drivers/%d", host, e.getDriverId()),
                                 "DriverUnit@NavigationLink", String.format("%s/drivers/%d/units/%d", host, e.getDriverId(), e.getUnitId()),
-                                "Actions@NavigationLink", String.format("%s/actions/%d", host, e.getActionId()),
+                                "Action@NavigationLink", String.format("%s/actions/%d", host, e.getActionId()),
                                 "Observations@NavigationLink", String.format("%s/events/%d/observations", host, e.getId()),
                                 "Locations@NavigationLink", String.format("%s/events/%d/observations/locations", host, e.getId())
                         ) : JsonObject.of()).mergeIn(JsonObject.of(
@@ -1277,7 +1277,7 @@ public class OpenAPIHandler {
                                 "actionId", e.getActionId(),
                                 "unitId", e.getUnitId(),
                                 "fromTime", DATE_TIME_FORMATTER.apply(e.getFromTime(), zone),
-                                "description", DATE_TIME_FORMATTER.apply(e.getToTime(), zone)
+                                "toTime", DATE_TIME_FORMATTER.apply(e.getToTime(), zone)
                         )).encode()))
                 .onFailure(rc::fail);
     }

+ 20 - 8
src/main/resources/openAPISpec.yaml

@@ -1431,6 +1431,7 @@ components:
       type: object
       required:
         - sensorId
+        - ioId
         - name
         - phenomenon
         - type
@@ -1474,6 +1475,10 @@ components:
         sensorId:
           type: integer
           format: int64
+        ioId:
+          type: integer
+          format: int32
+          minimum: 1
         name:
           type: string
         phenomenon:
@@ -1489,6 +1494,7 @@ components:
         Phenomenon@NavigationLink: "<domain>/phenomenons/15"
         Observations@NavigationLink: "<domain>/campaigns/1/units/25/sensors/105/observations"
         sensorId: 105
+        ioId: 98
         name: "Sensor 105"
         description: "Description of the sensor 105"
         type: "type of sensor"
@@ -2087,6 +2093,10 @@ components:
 
     Location:
       type: object
+      required:
+        - longitude
+        - latitude
+        - altitude
       properties:
         longitude:
           type: number
@@ -2364,7 +2374,7 @@ components:
     SensorBasicInfo:
       type: object
       required:
-        - id
+        - sensorId
         - name
       x-NavigationLinks:
         Sensor@NavigationLink:
@@ -2375,7 +2385,7 @@ components:
       properties:
         Sensor@NavigationLink:
           $ref: '#/components/schemas/SensorBasicInfo/x-NavigationLinks/Sensor@NavigationLink'
-        id:
+        sensorId:
           type: integer
           format: int64
         name:
@@ -2384,7 +2394,7 @@ components:
           type: string
       example:
         Sensor@NavigationLink: "<domain>/sensors/105"
-        id: 105
+        sensorId: 105
         name: "Sensor 105"
         description: "Description of the sensor 105"
 
@@ -2438,6 +2448,7 @@ components:
         Phenomenon@NavigationLink: "<domain>/phenomenons/15"
         Units@NavigationLink: "<domain>/sensors/105/units"
         sensorId: 105
+        ioId: 98
         name: "Sensor 105"
         description: "Description of the sensor 105"
         type: "type of sensor"
@@ -2535,8 +2546,6 @@ components:
     PhenomenonSensorBasicInfo:
       type: object
       required:
-        - Phenomenon@NavigationLink
-        - Sensor@NavigationLink
         - sensorId
         - name
       x-NavigationLinks:
@@ -2551,8 +2560,6 @@ components:
           x-graph-properties:
             linkTo: sensorIdGET
       properties:
-        Phenomenon@NavigationLink:
-          $ref: '#/components/schemas/PhenomenonSensorBasicInfo/x-NavigationLinks/Phenomenon@NavigationLink'
         Sensor@NavigationLink:
           $ref: '#/components/schemas/PhenomenonSensorBasicInfo/x-NavigationLinks/Sensor@NavigationLink'
         sensorId:
@@ -2563,7 +2570,6 @@ components:
         description:
           type: string
       example:
-        Phenomenon@NavigationLink: "<domain>/phenomenons/15"
         Sensor@NavigationLink: "<domain>/sensors/105"
         sensorId: 105
         name: "Sensor 105"
@@ -2761,6 +2767,9 @@ components:
 
     DriverActionDetailInfo:
       type: object
+      required:
+        - id
+        - name
       x-NavigationLinks:
         self@NavigationLink:
           type: string
@@ -2798,6 +2807,9 @@ components:
 
     DriverUnitActionDetailInfo:
       type: object
+      required:
+        - id
+        - name
       x-NavigationLinks:
         self@NavigationLink:
           type: string

+ 1904 - 6
src/test/java/cz/senslog/telemetry/server/ws/OpenAPIHandlerTest.java

@@ -5,8 +5,7 @@ import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import cz.senslog.telemetry.TestPropertiesUtils;
 import cz.senslog.telemetry.app.PropertyConfig;
-import cz.senslog.telemetry.database.domain.Campaign;
-import cz.senslog.telemetry.database.domain.CampaignUnit;
+import cz.senslog.telemetry.database.domain.*;
 import cz.senslog.telemetry.database.repository.SensLogRepository;
 import cz.senslog.telemetry.server.HttpVertxServer;
 import cz.senslog.telemetry.utils.Tuple;
@@ -40,7 +39,6 @@ import uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.time.*;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
@@ -50,8 +48,10 @@ import static cz.senslog.telemetry.server.ws.ContentType.JSON;
 import static cz.senslog.telemetry.server.ws.OpenAPIHandlerTest.OpenAPIResponseTyp.SUCCESS;
 import static cz.senslog.telemetry.server.ws.OpenAPIHandlerTest.OpenAPIResponseTyp.ERROR;
 import static java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME;
+import static java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME;
+import static java.util.Collections.emptyList;
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.*;
 
 @ExtendWith({VertxExtension.class, SystemStubsExtension.class})
 class OpenAPIHandlerTest {
@@ -154,7 +154,7 @@ class OpenAPIHandlerTest {
                         SUCCESS, JSON
                 ),
                 Arguments.of(
-                        Future.succeededFuture(Collections.emptyList()),
+                        Future.succeededFuture(emptyList()),
                         SUCCESS, JSON
                 ),
                 Arguments.of(
@@ -284,7 +284,7 @@ class OpenAPIHandlerTest {
                         SUCCESS, JSON
                 ),
                 Arguments.of(
-                        Future.succeededFuture(Collections.emptyList()),
+                        Future.succeededFuture(emptyList()),
                         SUCCESS, JSON
                 ),
                 Arguments.of(
@@ -371,4 +371,1902 @@ class OpenAPIHandlerTest {
                     testContext.completeNow();
                 })));
     }
+
+    private static Stream<Arguments> campaignIdUnitIdGET_dataSource() {
+        OffsetDateTime baseTimestamp = OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.UTC);
+        return Stream.of(
+                Arguments.of(
+                        Future.succeededFuture(CampaignUnit.of(1000, 1, "mock(name)", "mock(type)", "mock(imei)", "mock(description)", baseTimestamp, baseTimestamp.plusMonths(1))),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"),
+                        ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("campaignIdUnitIdGET_dataSource")
+    @DisplayName("API Spec Test: campaignIdUnitIdGET")
+    void campaignIdUnitIdGET_bySpec(Future<CampaignUnit> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findUnitByIdAndCampaignId(anyLong(), anyLong())).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("campaignIdUnitIdGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/campaigns/1/units/1000")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> campaignIdUnitIdGET_Params_dataSource() {
+        OffsetDateTime baseTimestamp = OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.UTC);
+        Future<CampaignUnit> future = Future.succeededFuture(CampaignUnit.of(1000, 1, "mock(name)", "mock(type)", "mock(imei)", "mock(description)", baseTimestamp, baseTimestamp.plusMonths(1)));
+
+        return Stream.of(
+                Arguments.of(future,
+                        "UTC",
+                        Tuple.of(
+                                OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.UTC).format(ISO_OFFSET_DATE_TIME),
+                                OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.UTC).plusMonths(1).format(ISO_OFFSET_DATE_TIME)
+                        ),
+                        false
+
+                ),
+                Arguments.of(future,
+                        "%2b2", // +2
+                        Tuple.of(
+                                OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.ofHours(2)).format(ISO_OFFSET_DATE_TIME),
+                                OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.ofHours(2)).plusMonths(1).format(ISO_OFFSET_DATE_TIME)
+                        ),
+                        true
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("campaignIdUnitIdGET_Params_dataSource")
+    @DisplayName("API Params Test: campaignIdUnitIdGET")
+    void campaignIdUnitIdGET_byParams(Future<CampaignUnit> dbFuture, String zoneParam, Tuple<String, String> expectedTimezones, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findUnitByIdAndCampaignId(anyLong(), anyLong())).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/campaigns/1/units/1000?zone=%s&navigationLinks=%s", zoneParam, navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode resJson = toJsonNode(b.toString());
+
+                    assertThat(resJson.get("fromTime").asText()).isEqualTo(expectedTimezones.item1());
+                    assertThat(resJson.get("toTime").asText()).isEqualTo(expectedTimezones.item2());
+
+                    assertThat(resJson.has("self@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Unit@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Campaign@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Sensors@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Observations@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Locations@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> campaignIdUnitIdSensorsGET_dataSource() {
+        return Stream.of(
+                Arguments.of(Future.succeededFuture(List.of(
+                        Sensor.of(105, "mock(name)", "M"),
+                        Sensor.of(106, "mock(name)", "M"),
+                        Sensor.of(107, "mock(name)", "M")
+                        )),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.succeededFuture(emptyList()),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"),
+                        ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("campaignIdUnitIdSensorsGET_dataSource")
+    @DisplayName("API Spec Test: campaignIdUnitIdSensorsGET")
+    void campaignIdUnitIdSensorsGET_bySpec(Future<List<Sensor>> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findSensorsByCampaignIdAndUnitId(anyLong(), anyLong())).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("campaignIdUnitIdSensorsGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/campaigns/1/units/1000/sensors")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> campaignIdUnitIdSensorsGET_Params_dataSource() {
+        Future<List<Sensor>> future = Future.succeededFuture(List.of(Sensor.of(105, "mock(name)", "M")));
+        return Stream.of(
+                Arguments.of(future, false),
+                Arguments.of(future, true)
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("campaignIdUnitIdSensorsGET_Params_dataSource")
+    @DisplayName("API Params Test: campaignIdUnitIdSensorsGET")
+    void campaignIdUnitIdGET_byParams(Future<List<Sensor>> dbFuture, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findSensorsByCampaignIdAndUnitId(anyLong(), anyLong())).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/campaigns/1/units/1000/sensors?navigationLinks=%s", navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode res = toJsonNode(b.toString());
+                    assertThat(res.size()).isEqualTo(1);
+                    JsonNode resJson = res.get(0);
+
+                    assertThat(resJson.has("CampaignSensor@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> campaignIdUnitIdSensorIdGET_dataSource() {
+        return Stream.of(
+                Arguments.of(Future.succeededFuture(
+                        Sensor.of(105, "mock(name)", "M", 98, Phenomenon.of(15, "mock(phenomenon)"), "mock(description)")),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("campaignIdUnitIdSensorIdGET_dataSource")
+    @DisplayName("API Spec Test: campaignIdUnitIdSensorIdGET")
+    void campaignIdUnitIdSensorIdGET_bySpec(Future<Sensor> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findSensorByCampaignIdAndUnitId(anyLong(), anyLong(), anyLong())).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("campaignIdUnitIdSensorIdGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/campaigns/1/units/1000/sensors/105")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> campaignIdUnitIdSensorIdGET_Params_dataSource() {
+        Future<Sensor> future = Future.succeededFuture(Sensor.of(105, "mock(name)", "M", 98, Phenomenon.of(15, "mock(phenomenon)"), "mock(description)"));
+        return Stream.of(
+                Arguments.of(future, false),
+                Arguments.of(future, true)
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("campaignIdUnitIdSensorIdGET_Params_dataSource")
+    @DisplayName("API Params Test: campaignIdUnitIdSensorIdGET")
+    void campaignIdUnitIdSensorIdGET_byParams(Future<Sensor> dbFuture, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findSensorByCampaignIdAndUnitId(anyLong(), anyLong(), anyLong())).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/campaigns/1/units/1000/sensors/105?navigationLinks=%s", navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode resJson = toJsonNode(b.toString());
+
+                    assertThat(resJson.has("self@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Sensor@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("CampaignUnit@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Phenomenon@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Observations@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> unitsGET_dataSource() {
+        return Stream.of(
+                Arguments.of(Future.succeededFuture(List.of(
+                            Unit.of(1000, "mock(name)", "mock(imei)", "mock(description)"),
+                            Unit.of(2000, "mock(name)", "mock(imei)", "mock(description)"),
+                            Unit.of(3000, "mock(name)", "mock(imei)", "mock(description)"))
+                        ),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.succeededFuture(emptyList()), SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("unitsGET_dataSource")
+    @DisplayName("API Spec Test: unitsGET")
+    void unitsGET_bySpec(Future<List<Unit>> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.allUnits()).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("unitsGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/units")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> unitIdGET_dataSource() {
+        return Stream.of(
+                Arguments.of(Future.succeededFuture(Unit.of(1000, "mock(name)", "mock(imei)", "mock(description)")),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("unitIdGET_dataSource")
+    @DisplayName("API Spec Test: unitIdGET")
+    void unitIdGET_bySpec(Future<Unit> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findUnitById(anyLong())).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("unitIdGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/units/1000")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> unitIdGET_Params_dataSource() {
+        Future<Unit> future = Future.succeededFuture(Unit.of(1000, "mock(name)", "mock(imei)", "mock(description)"));
+        return Stream.of(
+                Arguments.of(future, false),
+                Arguments.of(future, true)
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("unitIdGET_Params_dataSource")
+    @DisplayName("API Params Test: unitIdGET")
+    void unitIdGET_byParams(Future<Unit> dbFuture, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findUnitById(anyLong())).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/units/1000?navigationLinks=%s", navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode resJson = toJsonNode(b.toString());
+
+                    assertThat(resJson.has("self@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Sensors@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Campaigns@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Drivers@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> unitIdSensorsGET_dataSource() {
+        return Stream.of(
+                Arguments.of(Future.succeededFuture(List.of(
+                            Sensor.of(105, "mock(name)", "X"),
+                            Sensor.of(106, "mock(name)", "X"),
+                            Sensor.of(107, "mock(name)", "X"))
+                        ),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.succeededFuture(emptyList()), SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("unitIdSensorsGET_dataSource")
+    @DisplayName("API Spec Test: unitIdSensorsGET")
+    void unitIdSensorsGET_bySpec(Future<List<Sensor>> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findSensorsByUnitId(anyLong())).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("unitIdSensorsGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/units/1000/sensors")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> unitIdSensorsGET_Params_dataSource() {
+        Future<List<Sensor>> future = Future.succeededFuture(List.of(Sensor.of(105, "mock(name)", "X")));
+        return Stream.of(
+                Arguments.of(future, false),
+                Arguments.of(future, true)
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("unitIdSensorsGET_Params_dataSource")
+    @DisplayName("API Params Test: unitIdSensorsGET")
+    void unitIdSensorsGET_byParams(Future<List<Sensor>> dbFuture, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findSensorsByUnitId(anyLong())).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/units/1000/sensors?navigationLinks=%s", navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode res = toJsonNode(b.toString());
+                    assertThat(res.size()).isEqualTo(1);
+                    JsonNode resJson = res.get(0);
+
+                    assertThat(resJson.has("Sensor@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> unitIdCampaignsGET_dataSource() {
+        OffsetDateTime baseTimestamp = OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.UTC);
+        return Stream.of(
+                Arguments.of(Future.succeededFuture(List.of(
+                                Campaign.of(1, "mock(description)", baseTimestamp, baseTimestamp.plusMonths(1)),
+                                Campaign.of(2, "mock(description)", baseTimestamp.plusMonths(1), baseTimestamp.plusMonths(2)),
+                                Campaign.of(3, "mock(description)", baseTimestamp.plusMonths(2), baseTimestamp.plusMonths(3)))
+                        ),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.succeededFuture(emptyList()), SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("unitIdCampaignsGET_dataSource")
+    @DisplayName("API Spec Test: unitIdCampaignsGET")
+    void unitIdCampaignsGET_bySpec(Future<List<Campaign>> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findCampaignsByUnitId(anyLong(), any())).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("unitIdCampaignsGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/units/1000/campaigns")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> unitIdCampaignsGET_Params_dataSource() {
+        OffsetDateTime baseTimestamp = OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.UTC);
+        Future<List<Campaign>> future = Future.succeededFuture(List.of(Campaign.of(1, "mock(description)", baseTimestamp, baseTimestamp.plusMonths(1))));
+        return Stream.of(
+                Arguments.of(future,
+                        "UTC",
+                        Tuple.of(
+                                OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.UTC).format(ISO_OFFSET_DATE_TIME),
+                                OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.UTC).plusMonths(1).format(ISO_OFFSET_DATE_TIME)
+                        ),
+                        false
+
+                ),
+                Arguments.of(future,
+                        "%2b2", // +2
+                        Tuple.of(
+                                OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.ofHours(2)).format(ISO_OFFSET_DATE_TIME),
+                                OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.ofHours(2)).plusMonths(1).format(ISO_OFFSET_DATE_TIME)
+                        ),
+                        true
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("unitIdCampaignsGET_Params_dataSource")
+    @DisplayName("API Params Test: unitIdCampaignsGET")
+    void unitIdCampaignsGET_byParams(Future<List<Campaign>> dbFuture, String zoneParam, Tuple<String, String> expectedTimezones, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findCampaignsByUnitId(anyLong(), any())).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/units/1000/campaigns?zone=%s&navigationLinks=%s", zoneParam, navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode res = toJsonNode(b.toString());
+                    assertThat(res.size()).isEqualTo(1);
+                    JsonNode resJson = res.get(0);
+
+                    assertThat(resJson.get("fromTime").asText()).isEqualTo(expectedTimezones.item1());
+                    assertThat(resJson.get("toTime").asText()).isEqualTo(expectedTimezones.item2());
+
+                    assertThat(resJson.has("Campaign@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> unitIdDriversGET_dataSource() {
+        return Stream.of(
+                Arguments.of(Future.succeededFuture(List.of(
+                                Driver.of(1, "mock(name)"),
+                                Driver.of(2, "mock(name)"))
+                        ),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.succeededFuture(emptyList()), SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("unitIdDriversGET_dataSource")
+    @DisplayName("API Spec Test: unitIdDriversGET")
+    void unitIdDriversGET_bySpec(Future<List<Driver>> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findDriversByUnitId(anyLong())).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("unitIdDriversGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/units/1000/drivers")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> unitIdDriversGET_Params_dataSource() {
+        Future<List<Driver>> future = Future.succeededFuture(List.of(Driver.of(1, "mock(name)")));
+        return Stream.of(
+                Arguments.of(future, false),
+                Arguments.of(future, true)
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("unitIdDriversGET_Params_dataSource")
+    @DisplayName("API Params Test: unitIdDriversGET")
+    void unitIdDriversGET_byParams(Future<List<Driver>> dbFuture, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findDriversByUnitId(anyLong())).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/units/1000/drivers?navigationLinks=%s", navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode res = toJsonNode(b.toString());
+                    assertThat(res.size()).isEqualTo(1);
+                    JsonNode resJson = res.get(0);
+
+                    assertThat(resJson.has("Driver@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> sensorsGET_dataSource() {
+        return Stream.of(
+                Arguments.of(Future.succeededFuture(List.of(
+                                        Sensor.of(105, "mock(name)", "M", 98, Phenomenon.of(15, "mock(phenomenon)"), "mock(description)"),
+                                        Sensor.of(106, "mock(name)", "M", 99, Phenomenon.of(16, "mock(phenomenon)"), "mock(description)"),
+                                        Sensor.of(107, "mock(name)", "M", 100, Phenomenon.of(17, "mock(phenomenon)"), "mock(description)"))
+                        ),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.succeededFuture(emptyList()), SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("sensorsGET_dataSource")
+    @DisplayName("API Spec Test: sensorsGET")
+    void sensorsGET_bySpec(Future<List<Sensor>> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.allSensors()).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("sensorsGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/sensors")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> sensorsGET_Params_dataSource() {
+        Future<List<Sensor>> future = Future.succeededFuture(List.of(Sensor.of(105, "mock(name)", "M", 98, Phenomenon.of(15, "mock(phenomenon)"), "mock(description)")));
+        return Stream.of(
+                Arguments.of(future, false),
+                Arguments.of(future, true)
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("sensorsGET_Params_dataSource")
+    @DisplayName("API Params Test: sensorsGET")
+    void sensorsGET_byParams(Future<List<Sensor>> dbFuture, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.allSensors()).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/sensors?navigationLinks=%s", navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode res = toJsonNode(b.toString());
+                    assertThat(res.size()).isEqualTo(1);
+                    JsonNode resJson = res.get(0);
+
+                    assertThat(resJson.has("Sensor@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> sensorIdGET_dataSource() {
+        return Stream.of(
+                Arguments.of(Future.succeededFuture(
+                                Sensor.of(105, "mock(name)", "M", 98, Phenomenon.of(15, "mock(phenomenon)"), "mock(description)")
+                        ),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("sensorIdGET_dataSource")
+    @DisplayName("API Spec Test: sensorIdGET")
+    void sensorIdGET_bySpec(Future<Sensor> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findSensorById(anyLong())).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("sensorIdGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/sensors/105")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> sensorIdGET_Params_dataSource() {
+        Future<Sensor> future = Future.succeededFuture(Sensor.of(105, "mock(name)", "M", 98, Phenomenon.of(15, "mock(phenomenon)"), "mock(description)"));
+        return Stream.of(
+                Arguments.of(future, false),
+                Arguments.of(future, true)
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("sensorIdGET_Params_dataSource")
+    @DisplayName("API Params Test: sensorIdGET")
+    void sensorIdGET_byParams(Future<Sensor> dbFuture, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findSensorById(anyLong())).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/sensors/105?navigationLinks=%s", navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode resJson = toJsonNode(b.toString());
+
+                    assertThat(resJson.has("self@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Phenomenon@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Units@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> sensorIdUnitsGET_dataSource() {
+        return Stream.of(
+                Arguments.of(Future.succeededFuture(List.of(
+                            Unit.of(1000, "mock(name)", "mock(imei)", "mock(description)"),
+                            Unit.of(2000, "mock(name)", "mock(imei)", "mock(description)"),
+                            Unit.of(3000, "mock(name)", "mock(imei)", "mock(description)"))
+                        ),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.succeededFuture(emptyList()), SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("sensorIdUnitsGET_dataSource")
+    @DisplayName("API Spec Test: sensorIdUnitsGET")
+    void sensorIdUnitsGET_bySpec(Future<List<Unit>> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findUnitsBySensorId(anyLong())).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("sensorIdUnitsGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/sensors/105/units")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> sensorIdUnitsGET_Params_dataSource() {
+        Future<List<Unit>> future = Future.succeededFuture(List.of(Unit.of(2000, "mock(name)", "mock(imei)", "mock(description)")));
+        return Stream.of(
+                Arguments.of(future, false),
+                Arguments.of(future, true)
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("sensorIdUnitsGET_Params_dataSource")
+    @DisplayName("API Params Test: sensorIdUnitsGET")
+    void sensorIdUnitsGET_byParams(Future<List<Unit>> dbFuture, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findUnitsBySensorId(anyLong())).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/sensors/105/units?navigationLinks=%s", navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode res = toJsonNode(b.toString());
+                    assertThat(res.size()).isEqualTo(1);
+                    JsonNode resJson = res.get(0);
+
+                    assertThat(resJson.has("Unit@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> phenomenonsGET_dataSource() {
+        return Stream.of(
+                Arguments.of(Future.succeededFuture(List.of(
+                                Phenomenon.of(1, "mock(name)"),
+                                Phenomenon.of(2, "mock(name)"),
+                                Phenomenon.of(3, "mock(name)"))
+                        ),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.succeededFuture(emptyList()), SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("phenomenonsGET_dataSource")
+    @DisplayName("API Spec Test: phenomenonsGET")
+    void phenomenonsGET_bySpec(Future<List<Phenomenon>> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.allPhenomenons()).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("phenomenonsGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/phenomenons")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> phenomenonsGET_Params_dataSource() {
+        Future<List<Phenomenon>> future = Future.succeededFuture(List.of(Phenomenon.of(1, "mock(name)")));
+        return Stream.of(
+                Arguments.of(future, false),
+                Arguments.of(future, true)
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("phenomenonsGET_Params_dataSource")
+    @DisplayName("API Params Test: phenomenonsGET")
+    void phenomenonsGET_byParams(Future<List<Phenomenon>> dbFuture, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.allPhenomenons()).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/phenomenons?navigationLinks=%s", navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode res = toJsonNode(b.toString());
+                    assertThat(res.size()).isEqualTo(1);
+                    JsonNode resJson = res.get(0);
+
+                    assertThat(resJson.has("Phenomenon@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> phenomenonIdGET_dataSource() {
+        return Stream.of(
+                Arguments.of(
+                        Future.succeededFuture(Phenomenon.of(1, "mock(name)", "mock(uom)", "http://uomlink")),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("phenomenonIdGET_dataSource")
+    @DisplayName("API Spec Test: phenomenonIdGET")
+    void phenomenonIdGET_bySpec(Future<Phenomenon> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findPhenomenonById(anyLong())).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("phenomenonIdGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/phenomenons/1")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> phenomenonIdGET_Params_dataSource() {
+        Future<Phenomenon> future = Future.succeededFuture(Phenomenon.of(1, "mock(name)", "mock(uom)", "http://uomlink"));
+        return Stream.of(
+                Arguments.of(future, false),
+                Arguments.of(future, true)
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("phenomenonIdGET_Params_dataSource")
+    @DisplayName("API Params Test: phenomenonIdGET")
+    void phenomenonIdGET_byParams(Future<Phenomenon> dbFuture, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findPhenomenonById(anyLong())).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/phenomenons/1?navigationLinks=%s", navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode resJson = toJsonNode(b.toString());
+
+                    assertThat(resJson.has("self@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Sensors@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> phenomenonIdSensorsGET_dataSource() {
+        return Stream.of(
+                Arguments.of(
+                        Future.succeededFuture(List.of(
+                                Sensor.of(105, "mock(name)", "M", 98, Phenomenon.of(15, "mock(phenomenon)"), "mock(description)"),
+                                Sensor.of(106, "mock(name)", "M", 99, Phenomenon.of(17, "mock(phenomenon)"), "mock(description)"),
+                                Sensor.of(107, "mock(name)", "M", 100, Phenomenon.of(18, "mock(phenomenon)"), "mock(description)")
+                        )),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.succeededFuture(emptyList()), SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("phenomenonIdSensorsGET_dataSource")
+    @DisplayName("API Spec Test: phenomenonIdSensorsGET")
+    void phenomenonIdSensorsGET_bySpec(Future<List<Sensor>> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findSensorsByPhenomenonId(anyLong())).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("phenomenonIdSensorsGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/phenomenons/1/sensors")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> phenomenonIdSensorsGET_Params_dataSource() {
+        Future<List<Sensor>> future = Future.succeededFuture(List.of(Sensor.of(105, "mock(name)", "M", 98, Phenomenon.of(15, "mock(phenomenon)"), "mock(description)")));
+        return Stream.of(
+                Arguments.of(future, false),
+                Arguments.of(future, true)
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("phenomenonIdSensorsGET_Params_dataSource")
+    @DisplayName("API Params Test: phenomenonIdSensorsGET")
+    void phenomenonIdSensorsGET_byParams(Future<List<Sensor>> dbFuture, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findSensorsByPhenomenonId(anyLong())).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/phenomenons/1/sensors?navigationLinks=%s", navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode res = toJsonNode(b.toString());
+                    assertThat(res.size()).isEqualTo(1);
+                    JsonNode resJson = res.get(0);
+
+                    assertThat(resJson.has("Sensor@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> driversGET_dataSource() {
+        return Stream.of(
+                Arguments.of(
+                        Future.succeededFuture(List.of(
+                                Driver.of(1, "mock(name)"),
+                                Driver.of(2, "mock(name)"),
+                                Driver.of(3, "mock(name)")
+                        )),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.succeededFuture(emptyList()), SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("driversGET_dataSource")
+    @DisplayName("API Spec Test: driversGET")
+    void driversGET_bySpec(Future<List<Driver>> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.allDrivers()).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("driversGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/drivers")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> driversGET_Params_dataSource() {
+        Future<List<Driver>> future = Future.succeededFuture(List.of(Driver.of(1, "mock(name)")));
+        return Stream.of(
+                Arguments.of(future, false),
+                Arguments.of(future, true)
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("driversGET_Params_dataSource")
+    @DisplayName("API Params Test: driversGET")
+    void driversGET_byParams(Future<List<Driver>> dbFuture, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.allDrivers()).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/drivers?navigationLinks=%s", navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode res = toJsonNode(b.toString());
+                    assertThat(res.size()).isEqualTo(1);
+                    JsonNode resJson = res.get(0);
+
+                    assertThat(resJson.has("Driver@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> driverIdGET_dataSource() {
+        return Stream.of(
+                Arguments.of(
+                        Future.succeededFuture(Driver.of(1, "mock(name)")),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("driverIdGET_dataSource")
+    @DisplayName("API Spec Test: driverIdGET")
+    void driverIdGET_bySpec(Future<Driver> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findDriverById(anyInt())).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("driverIdGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/drivers/1")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> driverIdGET_Params_dataSource() {
+        Future<Driver> future = Future.succeededFuture(Driver.of(1, "mock(name)"));
+        return Stream.of(
+                Arguments.of(future, false),
+                Arguments.of(future, true)
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("driverIdGET_Params_dataSource")
+    @DisplayName("API Params Test: driverIdGET")
+    void driverIdGET_byParams(Future<Driver> dbFuture, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findDriverById(anyInt())).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/drivers/1?navigationLinks=%s", navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode resJson = toJsonNode(b.toString());
+
+                    assertThat(resJson.has("self@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Units@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Actions@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> driverIdUnitsGET_dataSource() {
+        return Stream.of(
+                Arguments.of(
+                        Future.succeededFuture(List.of(
+                                Unit.of(1000, "mock(name)", "mock(imei)", "mock(description)"),
+                                Unit.of(2000, "mock(name)", "mock(imei)", "mock(description)"),
+                                Unit.of(3000, "mock(name)", "mock(imei)", "mock(description)")
+                        )),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.succeededFuture(emptyList()), SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("driverIdUnitsGET_dataSource")
+    @DisplayName("API Spec Test: driverIdUnitsGET")
+    void driverIdUnitsGET_bySpec(Future<List<Unit>> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findUnitsByDriverId(anyInt(), any(), any())).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("driverIdUnitsGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/drivers/1/units")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> driverIdUnitsGET_Params_dataSource() {
+        Future<List<Unit>> future = Future.succeededFuture(List.of(Unit.of(1000, "mock(name)", "mock(imei)", "mock(description)")));
+        return Stream.of(
+                Arguments.of(future,
+                        OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.UTC).format(ISO_ZONED_DATE_TIME),
+                        OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.UTC).plusYears(1).format(ISO_ZONED_DATE_TIME),
+                        false
+                ),
+                Arguments.of(future,
+                        OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.UTC).format(ISO_ZONED_DATE_TIME),
+                        OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.UTC).plusYears(1).format(ISO_ZONED_DATE_TIME),
+                        true
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("driverIdUnitsGET_Params_dataSource")
+    @DisplayName("API Params Test: driverIdUnitsGET")
+    void driverIdUnitsGET_byParams(Future<List<Unit>> dbFuture, String from, String to, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findUnitsByDriverId(anyInt(), any(), any())).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/drivers/1/units?from=%s&to=%s&navigationLinks=%s", from, to, navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode res = toJsonNode(b.toString());
+                    assertThat(res.size()).isEqualTo(1);
+                    JsonNode resJson = res.get(0);
+
+                    assertThat(resJson.has("DriverUnit@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> driverIdUnitIdGET_dataSource() {
+        return Stream.of(
+                Arguments.of(
+                        Future.succeededFuture(Unit.of(1000, "mock(name)", "mock(imei)", "mock(description)")),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("driverIdUnitIdGET_dataSource")
+    @DisplayName("API Spec Test: driverIdUnitIdGET")
+    void driverIdUnitIdGET_bySpec(Future<Unit> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findUnitByIdAndDriverId(anyLong(), anyInt())).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("driverIdUnitIdGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/drivers/1/units/1000")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> driverIdUnitIdGET_Params_dataSource() {
+        Future<Unit> future = Future.succeededFuture(Unit.of(1000, "mock(name)", "mock(imei)", "mock(description)"));
+        return Stream.of(
+                Arguments.of(future, false),
+                Arguments.of(future, true)
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("driverIdUnitIdGET_Params_dataSource")
+    @DisplayName("API Params Test: driverIdUnitIdGET")
+    void driverIdUnitIdGET_byParams(Future<Unit> dbFuture, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findUnitByIdAndDriverId(anyLong(), anyInt())).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/drivers/1/units/1000?navigationLinks=%s", navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode resJson = toJsonNode(b.toString());
+
+                    assertThat(resJson.has("self@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Unit@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Actions@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> driverIdUnitIdActionsGET_dataSource() {
+        return Stream.of(
+                Arguments.of(
+                        Future.succeededFuture(List.of(
+                                Action.of(1, "mock(name)"),
+                                Action.of(2, "mock(name)"),
+                                Action.of(3, "mock(name)")
+                        )),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.succeededFuture(emptyList()), SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("driverIdUnitIdActionsGET_dataSource")
+    @DisplayName("API Spec Test: driverIdUnitIdActionsGET")
+    void driverIdUnitIdActionsGET_bySpec(Future<List<Action>> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findActionsByDriverIdAndUnitId(anyInt(), anyLong())).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("driverIdUnitIdActionsGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/drivers/1/units/1000/actions")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> driverIdUnitIdActionsGET_Params_dataSource() {
+        Future<List<Action>> future = Future.succeededFuture(List.of(Action.of(1, "mock(name)")));
+        return Stream.of(
+                Arguments.of(future, false),
+                Arguments.of(future, true)
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("driverIdUnitIdActionsGET_Params_dataSource")
+    @DisplayName("API Params Test: driverIdUnitIdActionsGET")
+    void driverIdUnitIdActionsGET_byParams(Future<List<Action>> dbFuture, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findActionsByDriverIdAndUnitId(anyInt(), anyLong())).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/drivers/1/units/1000/actions?navigationLinks=%s", navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode res = toJsonNode(b.toString());
+                    assertThat(res.size()).isEqualTo(1);
+                    JsonNode resJson = res.get(0);
+
+                    assertThat(resJson.has("DriverUntAction@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> driverIdActionsGET_dataSource() {
+        return Stream.of(
+                Arguments.of(
+                        Future.succeededFuture(List.of(
+                                Action.of(1, "mock(name)"),
+                                Action.of(2, "mock(name)"),
+                                Action.of(3, "mock(name)")
+                        )),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.succeededFuture(emptyList()), SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("driverIdActionsGET_dataSource")
+    @DisplayName("API Spec Test: driverIdActionsGET")
+    void driverIdActionsGET_bySpec(Future<List<Action>> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findActionsByDriverId(anyInt(), any(), any())).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("driverIdActionsGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/drivers/1/actions")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> driverIdActionsGET_Params_dataSource() {
+        Future<List<Action>> future = Future.succeededFuture(List.of(Action.of(1, "mock(name)")));
+        return Stream.of(
+                Arguments.of(future,
+                        OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.UTC).format(ISO_ZONED_DATE_TIME),
+                        OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.UTC).plusYears(1).format(ISO_ZONED_DATE_TIME),
+                        false
+                ),
+                Arguments.of(future,
+                        OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.UTC).format(ISO_ZONED_DATE_TIME),
+                        OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.UTC).plusYears(1).format(ISO_ZONED_DATE_TIME),
+                        true
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("driverIdActionsGET_Params_dataSource")
+    @DisplayName("API Params Test: driverIdActionsGET")
+    void driverIdActionsGET_byParams(Future<List<Action>> dbFuture, String from, String to, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findActionsByDriverId(anyInt(), any(), any())).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/drivers/1/actions?from=%s&to=%s&navigationLinks=%s", from, to, navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode res = toJsonNode(b.toString());
+                    assertThat(res.size()).isEqualTo(1);
+                    JsonNode resJson = res.get(0);
+
+                    assertThat(resJson.has("DriverAction@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> driverIdActionIdGET_dataSource() {
+        return Stream.of(
+                Arguments.of(
+                        Future.succeededFuture(Action.of(1, "mock(name)")),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("driverIdActionIdGET_dataSource")
+    @DisplayName("API Spec Test: driverIdActionIdGET")
+    void driverIdActionIdGET_bySpec(Future<Action> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findActionByIdAndDriverId(anyInt(), anyInt())).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("driverIdActionIdGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/drivers/1/actions/1")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> driverIdActionIdGET_Params_dataSource() {
+        Future<Action> future = Future.succeededFuture(Action.of(1, "mock(name)"));
+        return Stream.of(
+                Arguments.of(future, false),
+                Arguments.of(future, true)
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("driverIdActionIdGET_Params_dataSource")
+    @DisplayName("API Params Test: driverIdActionIdGET")
+    void driverIdActionIdGET_byParams(Future<Action> dbFuture, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findActionByIdAndDriverId(anyInt(), anyInt())).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/drivers/1/actions/1?navigationLinks=%s", navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode resJson = toJsonNode(b.toString());
+
+                    assertThat(resJson.has("self@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Driver@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Units@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> driverIdActionIdUnitsGET_dataSource() {
+        return Stream.of(
+                Arguments.of(
+                        Future.succeededFuture(List.of(
+                                Unit.of(1000, "mock(name)", "mock(imei)", "mock(description)"),
+                                Unit.of(2000, "mock(name)", "mock(imei)", "mock(description)"),
+                                Unit.of(3000, "mock(name)", "mock(imei)", "mock(description)")
+                        )),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.succeededFuture(emptyList()), SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("driverIdActionIdUnitsGET_dataSource")
+    @DisplayName("API Spec Test: driverIdActionIdUnitsGET")
+    void driverIdActionIdUnitsGET_bySpec(Future<List<Unit>> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findUnitsByDriverIdAndActionId(anyInt(), anyInt())).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("driverIdActionIdUnitsGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/drivers/1/actions/1/units")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> driverIdActionIdUnitsGET_Params_dataSource() {
+        Future<List<Unit>> future = Future.succeededFuture(List.of(Unit.of(1000, "mock(name)", "mock(imei)", "mock(description)")));
+        return Stream.of(
+                Arguments.of(future, false),
+                Arguments.of(future, true)
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("driverIdActionIdUnitsGET_Params_dataSource")
+    @DisplayName("API Params Test: driverIdActionIdUnitsGET")
+    void driverIdActionIdUnitsGET_byParams(Future<List<Unit>> dbFuture, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findUnitsByDriverIdAndActionId(anyInt(), anyInt())).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/drivers/1/actions/1/units?navigationLinks=%s", navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode res = toJsonNode(b.toString());
+                    assertThat(res.size()).isEqualTo(1);
+                    JsonNode resJson = res.get(0);
+
+                    assertThat(resJson.has("DriverActionUnit@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> driverIdActionIdUnitIdGET_dataSource() {
+        return Stream.of(
+                Arguments.of(
+                        Future.succeededFuture(Unit.of(1000, "mock(name)", "mock(imei)", "mock(description)")),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("driverIdActionIdUnitIdGET_dataSource")
+    @DisplayName("API Spec Test: driverIdActionIdUnitIdGET")
+    void driverIdActionIdUnitIdGET_bySpec(Future<Unit> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findUnitByIdAndDriverIdAndActionId(anyLong(), anyInt(), anyInt())).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("driverIdActionIdUnitIdGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/drivers/1/actions/1/units/1000")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> driverIdActionIdUnitIdGET_Params_dataSource() {
+        Future<Unit> future = Future.succeededFuture(Unit.of(1000, "mock(name)", "mock(imei)", "mock(description)"));
+        return Stream.of(
+                Arguments.of(future, false),
+                Arguments.of(future, true)
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("driverIdActionIdUnitIdGET_Params_dataSource")
+    @DisplayName("API Params Test: driverIdActionIdUnitIdGET")
+    void driverIdActionIdUnitIdGET_byParams(Future<Unit> dbFuture, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findUnitByIdAndDriverIdAndActionId(anyLong(), anyInt(), anyInt())).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/drivers/1/actions/1/units/1000?navigationLinks=%s", navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode resJson = toJsonNode(b.toString());
+
+                    assertThat(resJson.has("self@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("DriverAction@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Events@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Unit@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> driverIdUnitIdActionIdGET_dataSource() {
+        return Stream.of(
+                Arguments.of(
+                        Future.succeededFuture(Action.of(1, "mock(name)")),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("driverIdUnitIdActionIdGET_dataSource")
+    @DisplayName("API Spec Test: driverIdUnitIdActionIdGET")
+    void driverIdUnitIdActionIdGET_bySpec(Future<Action> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findActionByIdAndDriverIdAndUnitId(anyInt(), anyInt(), anyLong())).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("driverIdUnitIdActionIdGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/drivers/1/units/1000/actions/1")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> driverIdUnitIdActionIdGET_Params_dataSource() {
+        Future<Action> future = Future.succeededFuture(Action.of(1, "mock(name)"));
+        return Stream.of(
+                Arguments.of(future, false),
+                Arguments.of(future, true)
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("driverIdUnitIdActionIdGET_Params_dataSource")
+    @DisplayName("API Params Test: driverIdUnitIdActionIdGET")
+    void driverIdUnitIdActionIdGET_byParams(Future<Action> dbFuture, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findActionByIdAndDriverIdAndUnitId(anyInt(), anyInt(), anyLong())).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/drivers/1/units/1000/actions/1?navigationLinks=%s", navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode resJson = toJsonNode(b.toString());
+
+                    assertThat(resJson.has("self@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Driver@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("DriverUnit@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Events@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> driverIdUnitIdActionIdEventsGET_dataSource() {
+        OffsetDateTime baseTimestamp = OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.UTC);
+        return Stream.of(
+                Arguments.of(
+                        Future.succeededFuture(List.of(
+                                Event.of(1, 1, 1,1000, baseTimestamp, baseTimestamp.plusHours(8)),
+                                Event.of(2, 2, 2,2000, baseTimestamp, baseTimestamp.plusHours(8)),
+                                Event.of(3, 3, 3,3000, baseTimestamp, baseTimestamp.plusHours(8))
+                        )),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+                        Future.succeededFuture(emptyList()), SUCCESS, JSON
+                ),
+                Arguments.of(
+
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("driverIdUnitIdActionIdEventsGET_dataSource")
+    @DisplayName("API Spec Test: driverIdUnitIdActionIdEventsGET")
+    void driverIdUnitIdActionIdEventsGET_bySpec(Future<List<Event>> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findEventsByDriverIdAndUnitIdAndActionId(anyInt(), anyLong(), anyInt())).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("driverIdUnitIdActionIdEventsGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/drivers/1/units/1000/actions/1/events")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> driverIdUnitIdActionIdEventsGET_Params_dataSource() {
+        OffsetDateTime baseFrom = OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.UTC);
+        OffsetDateTime baseTo = OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.UTC).plusHours(8);
+
+        Future<List<Event>> future = Future.succeededFuture(List.of(Event.of(1, 1, 1,1000, baseFrom, baseTo)));
+
+        return Stream.of(
+                Arguments.of(future,
+                        "UTC",
+                        Tuple.of(
+                                baseFrom.format(ISO_OFFSET_DATE_TIME),
+                                baseTo.format(ISO_OFFSET_DATE_TIME)
+                        ),
+                        false
+
+                ),
+                Arguments.of(future,
+                        "%2b2", // +2
+                        Tuple.of(
+                                OffsetDateTime.ofInstant(baseFrom.toInstant(), ZoneOffset.ofHours(2)).format(ISO_OFFSET_DATE_TIME),
+                                OffsetDateTime.ofInstant(baseTo.toInstant(), ZoneOffset.ofHours(2)).format(ISO_OFFSET_DATE_TIME)
+                        ),
+                        true
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("driverIdUnitIdActionIdEventsGET_Params_dataSource")
+    @DisplayName("API Params Test: driverIdUnitIdActionIdEventsGET")
+    void driverIdUnitIdActionIdEventsGET_byParams(Future<List<Event>> dbFuture, String zoneParam, Tuple<String, String> expectedTimezones, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findEventsByDriverIdAndUnitIdAndActionId(anyInt(), anyLong(), anyInt())).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/drivers/1/units/1000/actions/1/events?zone=%s&navigationLinks=%s", zoneParam, navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode resJson = toJsonNode(b.toString());
+                    assertThat(resJson.size()).isEqualTo(1);
+
+                    JsonNode jsonObj1 = resJson.get(0);
+
+                    assertThat(jsonObj1.get("fromTime").asText()).isEqualTo(expectedTimezones.item1());
+                    assertThat(jsonObj1.get("toTime").asText()).isEqualTo(expectedTimezones.item2());
+
+                    assertThat(jsonObj1.has("Event@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> eventIdGET_dataSource() {
+        OffsetDateTime baseTimestamp = OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.UTC);
+        return Stream.of(
+                Arguments.of(
+                        Future.succeededFuture(Event.of(1, 1, 1,1000, baseTimestamp, baseTimestamp.plusHours(8))),
+                        SUCCESS, JSON
+                ),
+                Arguments.of(
+
+                        Future.failedFuture("Not found"), ERROR, JSON
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("eventIdGET_dataSource")
+    @DisplayName("API Spec Test: eventIdGET")
+    void eventIdGET_bySpec(Future<Event> dbFuture, OpenAPIResponseTyp responseTyp, ContentType contentType, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findEventById(anyLong())).thenReturn(dbFuture);
+
+        Operation operation = OPEN_API.getOperationById("eventIdGET");
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI("/events/1")
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    validateAssert(b.toString(), operation, responseTyp, contentType);
+                    testContext.completeNow();
+                })));
+    }
+
+    private static Stream<Arguments> eventIdGET_Params_dataSource() {
+        OffsetDateTime baseFrom = OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.UTC);
+        OffsetDateTime baseTo = OffsetDateTime.ofInstant(BASE_INSTANT_TIMESTAMP, ZoneOffset.UTC).plusHours(8);
+
+        Future<Event> future = Future.succeededFuture(Event.of(1, 1, 1,1000, baseFrom, baseTo));
+
+        return Stream.of(
+                Arguments.of(future,
+                        "UTC",
+                        Tuple.of(
+                                baseFrom.format(ISO_OFFSET_DATE_TIME),
+                                baseTo.format(ISO_OFFSET_DATE_TIME)
+                        ),
+                        false
+
+                ),
+                Arguments.of(future,
+                        "%2b2", // +2
+                        Tuple.of(
+                                OffsetDateTime.ofInstant(baseFrom.toInstant(), ZoneOffset.ofHours(2)).format(ISO_OFFSET_DATE_TIME),
+                                OffsetDateTime.ofInstant(baseTo.toInstant(), ZoneOffset.ofHours(2)).format(ISO_OFFSET_DATE_TIME)
+                        ),
+                        true
+                )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("eventIdGET_Params_dataSource")
+    @DisplayName("API Params Test: eventIdGET")
+    void eventIdGET_byParams(Future<Event> dbFuture, String zoneParam, Tuple<String, String> expectedTimezones, boolean navigationLinks, Vertx vertx, VertxTestContext testContext) {
+
+        Mockito.when(repo.findEventById(anyLong())).thenReturn(dbFuture);
+
+        RequestOptions reqOpt = new RequestOptions()
+                .setMethod(HttpMethod.GET).setPort(PORT).setHost(HOST).setURI(
+                        String.format("/events/1?zone=%s&navigationLinks=%s", zoneParam, navigationLinks))
+                .setHeaders(MultiMap.caseInsensitiveMultiMap()
+                        .add(HttpHeaders.ACCEPT, JSON.contentType()));
+
+        vertx.createHttpClient().request(reqOpt)
+                .compose(req -> req.send().compose(HttpClientResponse::body))
+                .onComplete(testContext.succeeding(b -> testContext.verify(() -> {
+                    JsonNode resJson = toJsonNode(b.toString());
+
+                    assertThat(resJson.get("fromTime").asText()).isEqualTo(expectedTimezones.item1());
+                    assertThat(resJson.get("toTime").asText()).isEqualTo(expectedTimezones.item2());
+
+                    assertThat(resJson.has("self@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Driver@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("DriverUnit@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Action@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Observations@NavigationLink")).isEqualTo(navigationLinks);
+                    assertThat(resJson.has("Locations@NavigationLink")).isEqualTo(navigationLinks);
+                    testContext.completeNow();
+                })));
+    }
 }