findById(UUID id);
-
- /**
- * Create or update a {@link TheEntity}.
- *
- * If the id already exists, the {@link TheEntity} will be overridden, hence update. If the id does
- * not already exist, a new {@link TheEntity} will be
- * created, hence create.
- *
- *
- * @param theEntity The {@link TheEntity} that will be saved.
- * @return the saved {@link TheEntity}.
- */
- @Override
- @CachePut(value = CACHE, key = "#p0.id")
- @PreAuthorize(
- "hasAuthority(T(de.muenchen.oss.wahllokalsystem.monitoringservice.security.AuthoritiesEnum).WLS_MONITORING_SERVICE_WRITE_THEENTITY.name())"
- )
- S save(S theEntity);
-
- /**
- * Create or update a collection of {@link TheEntity}.
- *
- * If the id already exists, the {@link TheEntity}s will be overridden, hence update. If the id does
- * not already exist, the new {@link TheEntity}s will be
- * created, hence create.
- *
- *
- * @param entities The {@link TheEntity} that will be saved.
- * @return the collection saved {@link TheEntity}.
- */
- @Override
- @PreAuthorize(
- "hasAuthority(T(de.muenchen.oss.wahllokalsystem.monitoringservice.security.AuthoritiesEnum).WLS_MONITORING_SERVICE_WRITE_THEENTITY.name())"
- )
- Iterable saveAll(Iterable entities);
-
- /**
- * Delete the {@link TheEntity} by a specified id.
- *
- * @param id the unique id of the {@link TheEntity} that will be deleted.
- */
- @Override
- @CacheEvict(value = CACHE, key = "#p0")
- @PreAuthorize(
- "hasAuthority(T(de.muenchen.oss.wahllokalsystem.monitoringservice.security.AuthoritiesEnum).WLS_MONITORING_SERVICE_DELETE_THEENTITY.name())"
- )
- void deleteById(UUID id);
-
- /**
- * Delete a {@link TheEntity} by entity.
- *
- * @param entity The {@link TheEntity} that will be deleted.
- */
- @Override
- @CacheEvict(value = CACHE, key = "#p0.id")
- @PreAuthorize(
- "hasAuthority(T(de.muenchen.oss.wahllokalsystem.monitoringservice.security.AuthoritiesEnum).WLS_MONITORING_SERVICE_DELETE_THEENTITY.name())"
- )
- void delete(TheEntity entity);
-
- /**
- * Delete multiple {@link TheEntity} entities by their id.
- *
- * @param entities The Iterable of {@link TheEntity} that will be deleted.
- */
- @Override
- @CacheEvict(value = CACHE, allEntries = true)
- @PreAuthorize(
- "hasAuthority(T(de.muenchen.oss.wahllokalsystem.monitoringservice.security.AuthoritiesEnum).WLS_MONITORING_SERVICE_DELETE_THEENTITY.name())"
- )
- void deleteAll(Iterable extends TheEntity> entities);
-
- /**
- * Delete all {@link TheEntity} entities.
- */
- @Override
- @CacheEvict(value = CACHE, allEntries = true)
- @PreAuthorize(
- "hasAuthority(T(de.muenchen.oss.wahllokalsystem.monitoringservice.security.AuthoritiesEnum).WLS_MONITORING_SERVICE_DELETE_THEENTITY.name())"
- )
- void deleteAll();
-
-}
diff --git a/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/rest/waehleranzahl/WaehleranzahlController.java b/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/rest/waehleranzahl/WaehleranzahlController.java
new file mode 100644
index 000000000..b28bbf0f5
--- /dev/null
+++ b/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/rest/waehleranzahl/WaehleranzahlController.java
@@ -0,0 +1,45 @@
+package de.muenchen.oss.wahllokalsystem.monitoringservice.rest.waehleranzahl;
+
+import de.muenchen.oss.wahllokalsystem.monitoringservice.rest.AbstractController;
+import de.muenchen.oss.wahllokalsystem.monitoringservice.service.waehleranzahl.WaehleranzahlService;
+import de.muenchen.oss.wahllokalsystem.wls.common.security.domain.BezirkUndWahlID;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import lombok.val;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/businessActions/wahlbeteiligung")
+@RequiredArgsConstructor
+@Slf4j
+public class WaehleranzahlController extends AbstractController {
+
+ private final WaehleranzahlService waehleranzahlService;
+ private final WaehleranzahlDTOMapper waehleranzahlDTOMapper;
+
+ @Operation(description = "Laden der zuvor gespeicherten Wahlbeteiligung für die Wahl {wahlID} für den Wahlbezirk {wahlbezirkID}.")
+ @GetMapping("/{wahlID}/{wahlbezirkID}")
+ ResponseEntity getWahlbeteiligung(@PathVariable("wahlID") final String wahlID, @PathVariable("wahlbezirkID") final String wahlbezirkID) {
+ val waehleranzahlModel = waehleranzahlService.getWahlbeteiligung(new BezirkUndWahlID(wahlID, wahlbezirkID));
+
+ return okWithBodyOrNoContent(waehleranzahlModel.map(waehleranzahlDTOMapper::toDTO));
+ }
+
+ @Operation(description = "Speichern und Weiterleiten der Wahlbeteiligung für die Wahl {wahlID} für den Wahlbezirk {wahlbezirkID}.")
+ @PostMapping("/{wahlID}/{wahlbezirkID}")
+ public void postWahlbeteiligung(@PathVariable("wahlbezirkID") final String wahlbezirkID, @PathVariable("wahlID") final String wahlID,
+ @RequestBody WaehleranzahlDTO waehleranzahl) {
+ log.info("postWahlbeteiligung {}", wahlbezirkID);
+
+ val waehleranzahlSetModel = waehleranzahlDTOMapper.toSetModel(new BezirkUndWahlID(wahlID, wahlbezirkID), waehleranzahl);
+
+ waehleranzahlService.postWahlbeteiligung(waehleranzahlSetModel);
+ }
+}
diff --git a/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/rest/waehleranzahl/WaehleranzahlDTO.java b/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/rest/waehleranzahl/WaehleranzahlDTO.java
new file mode 100644
index 000000000..35fb96c23
--- /dev/null
+++ b/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/rest/waehleranzahl/WaehleranzahlDTO.java
@@ -0,0 +1,11 @@
+package de.muenchen.oss.wahllokalsystem.monitoringservice.rest.waehleranzahl;
+
+import jakarta.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+import lombok.Builder;
+
+@Builder
+public record WaehleranzahlDTO(
+ @NotNull Long anzahlWaehler,
+ @NotNull LocalDateTime uhrzeit) {
+}
diff --git a/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/rest/waehleranzahl/WaehleranzahlDTOMapper.java b/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/rest/waehleranzahl/WaehleranzahlDTOMapper.java
new file mode 100644
index 000000000..291968704
--- /dev/null
+++ b/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/rest/waehleranzahl/WaehleranzahlDTOMapper.java
@@ -0,0 +1,13 @@
+package de.muenchen.oss.wahllokalsystem.monitoringservice.rest.waehleranzahl;
+
+import de.muenchen.oss.wahllokalsystem.monitoringservice.service.waehleranzahl.WaehleranzahlModel;
+import de.muenchen.oss.wahllokalsystem.wls.common.security.domain.BezirkUndWahlID;
+import org.mapstruct.Mapper;
+
+@Mapper
+public interface WaehleranzahlDTOMapper {
+
+ WaehleranzahlDTO toDTO(WaehleranzahlModel waehleranzahlModel);
+
+ WaehleranzahlModel toSetModel(BezirkUndWahlID bezirkUndWahlID, WaehleranzahlDTO waehleranzahlDTO);
+}
diff --git a/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlClient.java b/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlClient.java
new file mode 100644
index 000000000..6aeabdd14
--- /dev/null
+++ b/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlClient.java
@@ -0,0 +1,15 @@
+package de.muenchen.oss.wahllokalsystem.monitoringservice.service.waehleranzahl;
+
+import de.muenchen.oss.wahllokalsystem.wls.common.exception.WlsException;
+
+public interface WaehleranzahlClient {
+
+ /**
+ * @param waehleranzahlModel references a specific number of voters for a wahlId, wahlbezirkID and
+ * time
+ * @throws WlsException
+ * {@link de.muenchen.oss.wahllokalsystem.wls.common.exception.TechnischeWlsException}
+ * if there were trouble during communication
+ */
+ void postWahlbeteiligung(final WaehleranzahlModel waehleranzahlModel) throws WlsException;
+}
diff --git a/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlModel.java b/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlModel.java
new file mode 100644
index 000000000..f3f8fdfd0
--- /dev/null
+++ b/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlModel.java
@@ -0,0 +1,13 @@
+package de.muenchen.oss.wahllokalsystem.monitoringservice.service.waehleranzahl;
+
+import de.muenchen.oss.wahllokalsystem.wls.common.security.domain.BezirkUndWahlID;
+import jakarta.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+import lombok.Builder;
+
+@Builder
+public record WaehleranzahlModel(
+ @NotNull BezirkUndWahlID bezirkUndWahlID,
+ @NotNull long anzahlWaehler,
+ @NotNull LocalDateTime uhrzeit) {
+}
diff --git a/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlModelMapper.java b/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlModelMapper.java
new file mode 100644
index 000000000..84554e90e
--- /dev/null
+++ b/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlModelMapper.java
@@ -0,0 +1,13 @@
+package de.muenchen.oss.wahllokalsystem.monitoringservice.service.waehleranzahl;
+
+import de.muenchen.oss.wahllokalsystem.monitoringservice.domain.waehleranzahl.Waehleranzahl;
+import org.mapstruct.Mapper;
+
+@Mapper
+public interface WaehleranzahlModelMapper {
+
+ Waehleranzahl toEntity(WaehleranzahlModel waehleranzahlModel);
+
+ WaehleranzahlModel toModel(Waehleranzahl entity);
+
+}
diff --git a/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlService.java b/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlService.java
new file mode 100644
index 000000000..58218c212
--- /dev/null
+++ b/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlService.java
@@ -0,0 +1,43 @@
+package de.muenchen.oss.wahllokalsystem.monitoringservice.service.waehleranzahl;
+
+import de.muenchen.oss.wahllokalsystem.monitoringservice.domain.waehleranzahl.WaehleranzahlRepository;
+import de.muenchen.oss.wahllokalsystem.monitoringservice.exception.ExceptionConstants;
+import de.muenchen.oss.wahllokalsystem.wls.common.exception.util.ExceptionFactory;
+import de.muenchen.oss.wahllokalsystem.wls.common.security.domain.BezirkUndWahlID;
+import java.util.Optional;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import lombok.val;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Service;
+
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class WaehleranzahlService {
+
+ private final WaehleranzahlValidator waehleranzahlValidator;
+ private final WaehleranzahlRepository waehleranzahlRepository;
+ private final WaehleranzahlModelMapper waehleranzahlModelMapper;
+ private final ExceptionFactory exceptionFactory;
+ private final WaehleranzahlClient waehleranzahlClient;
+
+ @PreAuthorize("hasAuthority('Monitoring_BUSINESSACTION_GetWahlbeteiligung')")
+ public Optional getWahlbeteiligung(BezirkUndWahlID bezirkUndWahlID) {
+ waehleranzahlValidator.validWahlIdUndWahlbezirkIDOrThrow(bezirkUndWahlID);
+ val waehleranzahlFromRepo = waehleranzahlRepository.findById(bezirkUndWahlID);
+
+ return waehleranzahlFromRepo.map(waehleranzahlModelMapper::toModel);
+ }
+
+ @PreAuthorize("hasAuthority('Monitoring_BUSINESSACTION_PostWahlbeteiligung')")
+ public void postWahlbeteiligung(WaehleranzahlModel waehleranzahl) {
+ try {
+ waehleranzahlRepository.save(waehleranzahlModelMapper.toEntity(waehleranzahl));
+ } catch (Exception e) {
+ log.error("#postWahlbeteiligung: Die Wahlen konnten aufgrund eines Fehlers nicht gespeichert werden:", e);
+ throw exceptionFactory.createTechnischeWlsException(ExceptionConstants.POSTWAHLBETEILIGUNG_UNSAVEABLE);
+ }
+ waehleranzahlClient.postWahlbeteiligung(waehleranzahl);
+ }
+}
diff --git a/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlValidator.java b/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlValidator.java
new file mode 100644
index 000000000..32ddb42fb
--- /dev/null
+++ b/wls-monitoring-service/src/main/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlValidator.java
@@ -0,0 +1,22 @@
+package de.muenchen.oss.wahllokalsystem.monitoringservice.service.waehleranzahl;
+
+import de.muenchen.oss.wahllokalsystem.monitoringservice.exception.ExceptionConstants;
+import de.muenchen.oss.wahllokalsystem.wls.common.exception.util.ExceptionFactory;
+import de.muenchen.oss.wahllokalsystem.wls.common.security.domain.BezirkUndWahlID;
+import lombok.RequiredArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+
+@Component
+@RequiredArgsConstructor
+public class WaehleranzahlValidator {
+
+ private final ExceptionFactory exceptionFactory;
+
+ public void validWahlIdUndWahlbezirkIDOrThrow(final BezirkUndWahlID bezirkUndWahlID) {
+ if (bezirkUndWahlID == null || StringUtils.isEmpty(bezirkUndWahlID.getWahlID()) || StringUtils.isEmpty(bezirkUndWahlID.getWahlbezirkID()) ||
+ StringUtils.isBlank(bezirkUndWahlID.getWahlID()) || StringUtils.isBlank(bezirkUndWahlID.getWahlbezirkID())) {
+ throw exceptionFactory.createFachlicheWlsException(ExceptionConstants.GETWAHLBETEILIGUNG_SUCHKRITERIEN_UNVOLLSTAENDIG);
+ }
+ }
+}
diff --git a/wls-monitoring-service/src/main/resources/application.yml b/wls-monitoring-service/src/main/resources/application.yml
index 075fe3973..5e80699c6 100644
--- a/wls-monitoring-service/src/main/resources/application.yml
+++ b/wls-monitoring-service/src/main/resources/application.yml
@@ -5,6 +5,7 @@ spring:
group:
local:
- db-h2
+ - dummy.clients
flyway:
locations:
- classpath:db/migrations/{vendor}
@@ -24,6 +25,10 @@ security:
oauth2:
resource.user-info-uri: http://kubernetes.docker.internal:8100/auth/realms/${realm}/protocol/openid-connect/userinfo
+service:
+ info:
+ oid: WLS-MONITORING
+
# Define the local keycloak realm here
realm: wls_realm
@@ -57,3 +62,8 @@ management:
enabled: true
info.application.name: @project.artifactId@
info.application.version: @project.version@
+
+app:
+ clients:
+ eai:
+ basePath: http://localhost:39149
\ No newline at end of file
diff --git a/wls-monitoring-service/src/main/resources/db/migrations/h2/V0_1__createTableTheEntity.sql b/wls-monitoring-service/src/main/resources/db/migrations/h2/V0_1__createTableTheEntity.sql
deleted file mode 100644
index 1f2b83f72..000000000
--- a/wls-monitoring-service/src/main/resources/db/migrations/h2/V0_1__createTableTheEntity.sql
+++ /dev/null
@@ -1,5 +0,0 @@
-CREATE TABLE theEntity
-(
- id varchar2(36) NOT NULL primary key,
- textAttribute varchar2(8) NOT NULL
-)
\ No newline at end of file
diff --git a/wls-monitoring-service/src/main/resources/db/migrations/h2/V0_1__createTableWaehleranzahl.sql b/wls-monitoring-service/src/main/resources/db/migrations/h2/V0_1__createTableWaehleranzahl.sql
new file mode 100644
index 000000000..51482aa2c
--- /dev/null
+++ b/wls-monitoring-service/src/main/resources/db/migrations/h2/V0_1__createTableWaehleranzahl.sql
@@ -0,0 +1,9 @@
+CREATE TABLE Waehleranzahl
+(
+ wahlID VARCHAR(255) NOT NULL,
+ wahlbezirkID VARCHAR(255) NOT NULL,
+ anzahlWaehler BIGINT NOT NULL,
+ uhrzeit DATETIME NOT NULL,
+
+ PRIMARY KEY (wahlID, wahlbezirkID)
+);
\ No newline at end of file
diff --git a/wls-monitoring-service/src/main/resources/db/migrations/oracle/V0_1__createTableTheEntity.sql b/wls-monitoring-service/src/main/resources/db/migrations/oracle/V0_1__createTableTheEntity.sql
deleted file mode 100644
index 1f2b83f72..000000000
--- a/wls-monitoring-service/src/main/resources/db/migrations/oracle/V0_1__createTableTheEntity.sql
+++ /dev/null
@@ -1,5 +0,0 @@
-CREATE TABLE theEntity
-(
- id varchar2(36) NOT NULL primary key,
- textAttribute varchar2(8) NOT NULL
-)
\ No newline at end of file
diff --git a/wls-monitoring-service/src/main/resources/db/migrations/oracle/V0_1__createTableWaehleranzahl.sql b/wls-monitoring-service/src/main/resources/db/migrations/oracle/V0_1__createTableWaehleranzahl.sql
new file mode 100644
index 000000000..67e99c350
--- /dev/null
+++ b/wls-monitoring-service/src/main/resources/db/migrations/oracle/V0_1__createTableWaehleranzahl.sql
@@ -0,0 +1,9 @@
+CREATE TABLE Waehleranzahl
+(
+ wahlID VARCHAR(255) NOT NULL,
+ wahlbezirkID VARCHAR(255) NOT NULL,
+ anzahlWaehler NUMBER NOT NULL,
+ uhrzeit TIMESTAMP NOT NULL,
+
+ PRIMARY KEY (wahlID, wahlbezirkID)
+);
\ No newline at end of file
diff --git a/wls-monitoring-service/src/main/resources/openapis/openapi.eai.0.1.0.json b/wls-monitoring-service/src/main/resources/openapis/openapi.eai.0.1.0.json
new file mode 100644
index 000000000..de8c135d1
--- /dev/null
+++ b/wls-monitoring-service/src/main/resources/openapis/openapi.eai.0.1.0.json
@@ -0,0 +1 @@
+{"openapi":"3.0.1","info":{"title":"EAI Service","contact":{"name":"Your Name","email":"Your E-Mail-Address"},"version":"0.1.0"},"servers":[{"url":"http://localhost:8080","description":"Generated server url"}],"security":[{"bearerAuth":[]}],"paths":{"/wahlvorstaende/anwesenheit":{"put":{"tags":["wahlvorstand-controller"],"description":"Aktualisieren der Anwesenheit der Wahlvorstandsmitglieder eines bestimmten Wahlbezirkes","operationId":"saveAnwesenheit","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WahlvorstandsaktualisierungDTO"}}},"required":true},"responses":{"200":{"description":"OK"},"400":{"description":"request body validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}},"404":{"description":"resource not found"},"500":{"description":"unhandled error during communication with other system","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}}}}},"/wahllokalzustand":{"post":{"tags":["wahllokalzustand-controller"],"operationId":"saveWahllokalZustand","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WahllokalZustandDTO"}}},"required":true},"responses":{"200":{"description":"OK"},"400":{"description":"request body validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}},"404":{"description":"resource not found"},"500":{"description":"unhandled error during communication with other system","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}}}}},"/wahlergebnis":{"post":{"tags":["wahlergebnis-controller"],"operationId":"saveWahlergebnismeldung","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErgebnismeldungDTO"}}},"required":true},"responses":{"200":{"description":"OK"},"400":{"description":"request body validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}},"404":{"description":"resource not found"},"500":{"description":"unhandled error during communication with other system","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}}}}},"/wahlbeteiligung":{"post":{"tags":["wahlbeteiligung-controller"],"operationId":"saveWahlbeteiligung","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WahlbeteiligungsMeldungDTO"}}},"required":true},"responses":{"200":{"description":"OK"},"400":{"description":"request body validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}},"404":{"description":"resource not found"},"500":{"description":"unhandled error during communication with other system","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}}}}},"/wahlvorstaende":{"get":{"tags":["wahlvorstand-controller"],"description":"Abrufen des Wahlvorstandes für einen bestimmten Wahlbezirk","operationId":"loadWahlvorstand","parameters":[{"name":"wahlbezirkID","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/WahlvorstandDTO"}}}},"400":{"description":"request body validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}},"404":{"description":"resource not found"},"500":{"description":"unhandled error during communication with other system","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}}}}},"/wahldaten/wahltage":{"get":{"tags":["wahldaten-controller"],"operationId":"loadWahltageSinceIncluding","parameters":[{"name":"includingSince","in":"query","required":true,"schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"uniqueItems":true,"type":"array","items":{"$ref":"#/components/schemas/WahltagDTO"}}}}},"400":{"description":"request body validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}},"404":{"description":"resource not found"},"500":{"description":"unhandled error during communication with other system","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}}}}},"/wahldaten/wahlen":{"get":{"tags":["wahldaten-controller"],"operationId":"loadWahlen","parameters":[{"name":"forDate","in":"query","required":true,"schema":{"type":"string","format":"date"}},{"name":"withNummer","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"uniqueItems":true,"type":"array","items":{"$ref":"#/components/schemas/WahlDTO"}}}}},"400":{"description":"request body validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}},"404":{"description":"resource not found"},"500":{"description":"unhandled error during communication with other system","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}}}}},"/wahldaten/wahlbezirke/{wahlbezirkID}/wahlberechtigte":{"get":{"tags":["wahldaten-controller"],"operationId":"loadWahlberechtigte","parameters":[{"name":"wahlbezirkID","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WahlberechtigteDTO"}}}}},"400":{"description":"request body validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}},"404":{"description":"resource not found"},"500":{"description":"unhandled error during communication with other system","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}}}}},"/wahldaten/wahlbezirk":{"get":{"tags":["wahldaten-controller"],"operationId":"loadWahlbezirke","parameters":[{"name":"forDate","in":"query","required":true,"schema":{"type":"string","format":"date"}},{"name":"withNummer","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"uniqueItems":true,"type":"array","items":{"$ref":"#/components/schemas/WahlbezirkDTO"}}}}},"400":{"description":"request body validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}},"404":{"description":"resource not found"},"500":{"description":"unhandled error during communication with other system","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}}}}},"/wahldaten/basisdaten":{"get":{"tags":["wahldaten-controller"],"operationId":"loadBasisdaten","parameters":[{"name":"forDate","in":"query","required":true,"schema":{"type":"string","format":"date"}},{"name":"withNummer","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/BasisdatenDTO"}}}},"400":{"description":"request body validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}},"404":{"description":"resource not found"},"500":{"description":"unhandled error during communication with other system","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}}}}},"/vorschlaege/wahl/{wahlID}/{wahlbezirkID}":{"get":{"tags":["wahlvorschlag-controller"],"operationId":"loadWahlvorschlaege","parameters":[{"name":"wahlID","in":"path","required":true,"schema":{"type":"string"}},{"name":"wahlbezirkID","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/WahlvorschlaegeDTO"}}}},"400":{"description":"request body validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}},"404":{"description":"resource not found"},"500":{"description":"unhandled error during communication with other system","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}}}}},"/vorschlaege/wahl/{wahlID}/liste":{"get":{"tags":["wahlvorschlag-controller"],"operationId":"loadWahlvorschlaegeListe","parameters":[{"name":"forDate","in":"query","required":true,"schema":{"type":"string","format":"date"}},{"name":"wahlID","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/WahlvorschlaegeListeDTO"}}}},"400":{"description":"request body validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}},"404":{"description":"resource not found"},"500":{"description":"unhandled error during communication with other system","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}}}}},"/vorschlaege/referendum/{wahlID}/{wahlbezirkID}":{"get":{"tags":["wahlvorschlag-controller"],"operationId":"loadReferendumvorlagen","parameters":[{"name":"wahlID","in":"path","required":true,"schema":{"type":"string"}},{"name":"wahlbezirkID","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ReferendumvorlagenDTO"}}}},"400":{"description":"request body validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}},"404":{"description":"resource not found"},"500":{"description":"unhandled error during communication with other system","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WlsExceptionDTO"}}}}}}}},"components":{"schemas":{"WahlvorstandsaktualisierungDTO":{"required":["anwesenheitBeginn","mitglieder","wahlbezirkID"],"type":"object","properties":{"wahlbezirkID":{"type":"string"},"mitglieder":{"maxItems":2147483647,"minItems":1,"uniqueItems":true,"type":"array","items":{"$ref":"#/components/schemas/WahlvorstandsmitgliedAktualisierungDTO"}},"anwesenheitBeginn":{"type":"string","format":"date-time"}}},"WahlvorstandsmitgliedAktualisierungDTO":{"required":["anwesend","identifikator"],"type":"object","properties":{"identifikator":{"type":"string"},"anwesend":{"type":"boolean"}}},"DruckzustandDTO":{"required":["niederschriftDruckUhrzeit","niederschriftSendenUhrzeit","schnellmeldungDruckUhrzeit","schnellmeldungSendenUhrzeit","wahlID"],"type":"object","properties":{"wahlID":{"type":"string"},"schnellmeldungSendenUhrzeit":{"type":"string","format":"date-time"},"niederschriftSendenUhrzeit":{"type":"string","format":"date-time"},"schnellmeldungDruckUhrzeit":{"type":"string","format":"date-time"},"niederschriftDruckUhrzeit":{"type":"string","format":"date-time"}}},"WahllokalZustandDTO":{"required":["druckzustaende","letzteAbmeldung","wahlbezirkID","zuletztGesehen"],"type":"object","properties":{"wahlbezirkID":{"type":"string"},"zuletztGesehen":{"type":"string","format":"date-time"},"letzteAbmeldung":{"type":"string","format":"date-time"},"druckzustaende":{"maxItems":2147483647,"minItems":1,"uniqueItems":true,"type":"array","items":{"$ref":"#/components/schemas/DruckzustandDTO"}}}},"AWerteDTO":{"type":"object","properties":{"a1":{"type":"integer","format":"int64"},"a2":{"type":"integer","format":"int64"}}},"BWerteDTO":{"type":"object","properties":{"b":{"type":"integer","format":"int64"},"b1":{"type":"integer","format":"int64"},"b2":{"type":"integer","format":"int64"}}},"ErgebnisDTO":{"required":["ergebnis","kandidatID","stimmenart","wahlvorschlagID","wahlvorschlagsordnungszahl"],"type":"object","properties":{"stimmenart":{"type":"string"},"wahlvorschlagsordnungszahl":{"type":"integer","format":"int64"},"ergebnis":{"type":"integer","format":"int64"},"wahlvorschlagID":{"type":"string"},"kandidatID":{"type":"string"}}},"ErgebnismeldungDTO":{"required":["wahlID","wahlbezirkID"],"type":"object","properties":{"wahlbezirkID":{"type":"string"},"wahlID":{"type":"string"},"meldungsart":{"type":"string","enum":["NIEDERSCHRIFT","SCHNELLMELDUNG"]},"aWerte":{"$ref":"#/components/schemas/AWerteDTO"},"bWerte":{"$ref":"#/components/schemas/BWerteDTO"},"wahlbriefeWerte":{"$ref":"#/components/schemas/WahlbriefeWerteDTO"},"ungueltigeStimmzettels":{"type":"array","items":{"$ref":"#/components/schemas/UngueltigeStimmzettelDTO"}},"ungueltigeStimmzettelAnzahl":{"type":"integer","format":"int64"},"ergebnisse":{"type":"array","items":{"$ref":"#/components/schemas/ErgebnisDTO"}},"wahlart":{"type":"string","enum":["BAW","BEB","BTW","BZW","EUW","LTW","MBW","OBW","SRW","SVW","VE"]}}},"UngueltigeStimmzettelDTO":{"type":"object","properties":{"stimmenart":{"type":"string"},"anzahl":{"type":"integer","format":"int64"},"wahlvorschlagID":{"type":"string"}}},"WahlbriefeWerteDTO":{"type":"object","properties":{"zurueckgewiesenGesamt":{"type":"integer","format":"int64"}}},"WahlbeteiligungsMeldungDTO":{"required":["anzahlWaehler","meldeZeitpunkt","wahlID","wahlbezirkID"],"type":"object","properties":{"wahlID":{"type":"string"},"wahlbezirkID":{"type":"string"},"anzahlWaehler":{"type":"integer","format":"int64"},"meldeZeitpunkt":{"type":"string","format":"date-time"}}},"WahlvorstandDTO":{"required":["mitglieder","wahlbezirkID"],"type":"object","properties":{"wahlbezirkID":{"type":"string"},"mitglieder":{"maxItems":2147483647,"minItems":1,"uniqueItems":true,"type":"array","items":{"$ref":"#/components/schemas/WahlvorstandsmitgliedDTO"}}}},"WahlvorstandsmitgliedDTO":{"required":["anwesend","funktion","identifikator","nachname","vorname"],"type":"object","properties":{"identifikator":{"type":"string"},"vorname":{"type":"string"},"nachname":{"type":"string"},"funktion":{"type":"string","enum":["W","SB","SWB","SSB","B"]},"anwesend":{"type":"boolean"}}},"WahltagDTO":{"required":["beschreibung","identifikator","nummer","tag"],"type":"object","properties":{"identifikator":{"type":"string"},"tag":{"type":"string","format":"date"},"beschreibung":{"type":"string"},"nummer":{"type":"string"}}},"WahlDTO":{"required":["identifikator","name","nummer","wahlart","wahltag"],"type":"object","properties":{"identifikator":{"type":"string"},"name":{"type":"string"},"wahlart":{"type":"string","enum":["BAW","BEB","BTW","BZW","EUW","LTW","MBW","OBW","SRW","SVW","VE"]},"wahltag":{"type":"string","format":"date"},"nummer":{"type":"string"}}},"WahlberechtigteDTO":{"required":["a1","a2","a3","wahlID","wahlbezirkID"],"type":"object","properties":{"wahlID":{"type":"string"},"wahlbezirkID":{"type":"string"},"a1":{"type":"integer","format":"int64"},"a2":{"type":"integer","format":"int64"},"a3":{"type":"integer","format":"int64"}}},"WahlbezirkDTO":{"required":["identifikator","nummer","wahlID","wahlbezirkArt","wahlnummer","wahltag"],"type":"object","properties":{"identifikator":{"type":"string"},"wahlbezirkArt":{"type":"string","enum":["UWB","BWB"]},"nummer":{"type":"string"},"wahltag":{"type":"string","format":"date"},"wahlnummer":{"type":"string"},"wahlID":{"type":"string"}}},"BasisdatenDTO":{"required":["basisstrukturdaten","stimmzettelgebiete","wahlbezirke","wahlen"],"type":"object","properties":{"basisstrukturdaten":{"uniqueItems":true,"type":"array","items":{"$ref":"#/components/schemas/BasisstrukturdatenDTO"}},"wahlen":{"uniqueItems":true,"type":"array","items":{"$ref":"#/components/schemas/WahlDTO"}},"wahlbezirke":{"uniqueItems":true,"type":"array","items":{"$ref":"#/components/schemas/WahlbezirkDTO"}},"stimmzettelgebiete":{"uniqueItems":true,"type":"array","items":{"$ref":"#/components/schemas/StimmzettelgebietDTO"}}}},"BasisstrukturdatenDTO":{"required":["stimmzettelgebietID","wahlID","wahlbezirkID","wahltag"],"type":"object","properties":{"wahlID":{"type":"string"},"stimmzettelgebietID":{"type":"string"},"wahlbezirkID":{"type":"string"},"wahltag":{"type":"string","format":"date"}}},"StimmzettelgebietDTO":{"required":["stimmzettelgebietsart"],"type":"object","properties":{"identifikator":{"type":"string"},"nummer":{"type":"string"},"name":{"type":"string"},"wahltag":{"type":"string","format":"date"},"stimmzettelgebietsart":{"type":"string","enum":["SB","SG","SK","WK"]}}},"KandidatDTO":{"required":["direktkandidat","einzelbewerber","identifikator","listenposition","name","tabellenSpalteInNiederschrift"],"type":"object","properties":{"identifikator":{"type":"string"},"name":{"type":"string"},"listenposition":{"type":"integer","format":"int64"},"direktkandidat":{"type":"boolean"},"tabellenSpalteInNiederschrift":{"type":"integer","format":"int64"},"einzelbewerber":{"type":"boolean"}}},"WahlvorschlaegeDTO":{"required":["stimmzettelgebietID","wahlID","wahlbezirkID","wahlvorschlaege"],"type":"object","properties":{"wahlbezirkID":{"type":"string"},"wahlID":{"type":"string"},"stimmzettelgebietID":{"type":"string"},"wahlvorschlaege":{"maxItems":2147483647,"minItems":1,"uniqueItems":true,"type":"array","items":{"$ref":"#/components/schemas/WahlvorschlagDTO"}}}},"WahlvorschlagDTO":{"required":["erhaeltStimmen","identifikator","kurzname","ordnungszahl"],"type":"object","properties":{"identifikator":{"type":"string"},"ordnungszahl":{"type":"integer","format":"int64"},"kurzname":{"type":"string"},"erhaeltStimmen":{"type":"boolean"},"kandidaten":{"uniqueItems":true,"type":"array","items":{"$ref":"#/components/schemas/KandidatDTO"}}}},"WahlvorschlaegeListeDTO":{"required":["wahlID","wahlvorschlaegeliste"],"type":"object","properties":{"wahlID":{"type":"string"},"wahlvorschlaegeliste":{"maxItems":2147483647,"minItems":1,"uniqueItems":true,"type":"array","items":{"$ref":"#/components/schemas/WahlvorschlaegeDTO"}}}},"ReferendumoptionDTO":{"required":["id","name"],"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"position":{"type":"integer","format":"int64"}}},"ReferendumvorlageDTO":{"required":["frage","kurzname","ordnungszahl","referendumoptionen","wahlvorschlagID"],"type":"object","properties":{"wahlvorschlagID":{"type":"string"},"ordnungszahl":{"type":"integer","format":"int64"},"kurzname":{"type":"string"},"frage":{"type":"string"},"referendumoptionen":{"maxItems":2147483647,"minItems":1,"uniqueItems":true,"type":"array","items":{"$ref":"#/components/schemas/ReferendumoptionDTO"}}}},"ReferendumvorlagenDTO":{"required":["referendumvorlagen","stimmzettelgebietID"],"type":"object","properties":{"stimmzettelgebietID":{"type":"string"},"referendumvorlagen":{"maxItems":2147483647,"minItems":1,"uniqueItems":true,"type":"array","items":{"$ref":"#/components/schemas/ReferendumvorlageDTO"}}}},"WlsExceptionDTO":{"required":["category","code","message","service"],"type":"object","properties":{"category":{"type":"string","enum":["F","T","S","I"]},"code":{"type":"string"},"service":{"type":"string"},"message":{"type":"string"}}}},"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}}}}
\ No newline at end of file
diff --git a/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/TestConstants.java b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/TestConstants.java
index 4baaa9a9e..6668e6af7 100644
--- a/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/TestConstants.java
+++ b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/TestConstants.java
@@ -5,12 +5,7 @@
package de.muenchen.oss.wahllokalsystem.monitoringservice;
import lombok.AccessLevel;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
import lombok.NoArgsConstructor;
-import lombok.Setter;
-import lombok.ToString;
-import org.springframework.hateoas.RepresentationModel;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class TestConstants {
@@ -19,15 +14,4 @@ public final class TestConstants {
public static final String SPRING_NO_SECURITY_PROFILE = "no-security";
- @NoArgsConstructor
- @Getter
- @Setter
- @EqualsAndHashCode(callSuper = true)
- @ToString(callSuper = true)
- public static class TheEntityDto extends RepresentationModel {
-
- private String textAttribute;
-
- }
-
}
diff --git a/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/client/waehleranzahl/WaehleranzahlClientImplTest.java b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/client/waehleranzahl/WaehleranzahlClientImplTest.java
new file mode 100644
index 000000000..f255a8201
--- /dev/null
+++ b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/client/waehleranzahl/WaehleranzahlClientImplTest.java
@@ -0,0 +1,66 @@
+package de.muenchen.oss.wahllokalsystem.monitoringservice.client.waehleranzahl;
+
+import de.muenchen.oss.wahllokalsystem.monitoringservice.eai.aou.client.WahlbeteiligungControllerApi;
+import de.muenchen.oss.wahllokalsystem.monitoringservice.eai.aou.model.WahlbeteiligungsMeldungDTO;
+import de.muenchen.oss.wahllokalsystem.monitoringservice.service.waehleranzahl.WaehleranzahlModel;
+import de.muenchen.oss.wahllokalsystem.wls.common.security.domain.BezirkUndWahlID;
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import lombok.val;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+@ExtendWith(MockitoExtension.class)
+class WaehleranzahlClientImplTest {
+
+ @Mock
+ WahlbeteiligungControllerApi wahlbeteiligungControllerApi;
+
+ @Mock
+ WaehleranzahlClientMapper waehleranzahlClientMapper;
+
+ @InjectMocks
+ WaehleranzahlClientImpl unitUnderTest;
+
+ @Nested
+ class PostWahlbeteiligung {
+
+ @Test
+ void should_callEaiApiWithDTO_when_clientIsCalledWithModel() {
+ val waehleranzahlModel = new WaehleranzahlModel(new BezirkUndWahlID("wahlID01", "wahlbezirkID01"), 99L, LocalDateTime.now());
+ val mockedWahlbeteiligungsMeldungDTO = createWahlbeteiligungsMeldungDTO();
+ Mockito.when(waehleranzahlClientMapper.fromModelToRemoteClientDTO(waehleranzahlModel)).thenReturn(mockedWahlbeteiligungsMeldungDTO);
+
+ unitUnderTest.postWahlbeteiligung(waehleranzahlModel);
+ Mockito.verify(wahlbeteiligungControllerApi).saveWahlbeteiligung(mockedWahlbeteiligungsMeldungDTO);
+ }
+
+ @Test
+ void should_notThrowException_when_eaiApiThrowsAnyException() {
+ val waehleranzahlModel = new WaehleranzahlModel(new BezirkUndWahlID("wahlID01", "wahlbezirkID01"), 99L, LocalDateTime.now());
+ val mockedWahlbeteiligungsMeldungDTO = createWahlbeteiligungsMeldungDTO();
+ Mockito.when(waehleranzahlClientMapper.fromModelToRemoteClientDTO(waehleranzahlModel)).thenReturn(mockedWahlbeteiligungsMeldungDTO);
+
+ val mockedApiException = new IllegalArgumentException("Nix-Connect");
+ Mockito.doThrow(mockedApiException).when(wahlbeteiligungControllerApi).saveWahlbeteiligung(mockedWahlbeteiligungsMeldungDTO);
+
+ Assertions.assertThatNoException().isThrownBy(() -> unitUnderTest.postWahlbeteiligung(waehleranzahlModel));
+ }
+
+ private WahlbeteiligungsMeldungDTO createWahlbeteiligungsMeldungDTO() {
+ val wahlID = "wahlID01";
+ val wahlbezirkID = "wahlbezirkID01";
+ val anzahlWahler = 99L;
+ val meldeZeitpunkt = OffsetDateTime.now();
+ return new WahlbeteiligungsMeldungDTO().wahlID(wahlID).wahlbezirkID(wahlbezirkID).anzahlWaehler(anzahlWahler)
+ .meldeZeitpunkt(meldeZeitpunkt);
+ }
+ }
+
+}
diff --git a/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/client/waehleranzahl/WaehleranzahlClientMapperTest.java b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/client/waehleranzahl/WaehleranzahlClientMapperTest.java
new file mode 100644
index 000000000..d10dd75af
--- /dev/null
+++ b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/client/waehleranzahl/WaehleranzahlClientMapperTest.java
@@ -0,0 +1,67 @@
+package de.muenchen.oss.wahllokalsystem.monitoringservice.client.waehleranzahl;
+
+import de.muenchen.oss.wahllokalsystem.monitoringservice.eai.aou.model.WahlbeteiligungsMeldungDTO;
+import de.muenchen.oss.wahllokalsystem.monitoringservice.service.waehleranzahl.WaehleranzahlModel;
+import de.muenchen.oss.wahllokalsystem.wls.common.security.domain.BezirkUndWahlID;
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import lombok.val;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mapstruct.factory.Mappers;
+
+public class WaehleranzahlClientMapperTest {
+
+ private final WaehleranzahlClientMapper unitUnderTest = Mappers.getMapper(WaehleranzahlClientMapper.class);
+
+ @Nested
+ class FromModelToRemoteClientDTO {
+
+ @Test
+ void should_return_RemoteClientDTO_when_modelIsGiven() {
+ val wahlID = "wahlID01";
+ val wahlbezirkID = "wahlbezirkID01";
+ val anzahlWahler = 99L;
+ val meldeZeitpunkt = LocalDateTime.now();
+ val bezirkUndWahlID = new BezirkUndWahlID(wahlID, wahlbezirkID);
+
+ val waehleranzahlModel = new WaehleranzahlModel(bezirkUndWahlID, anzahlWahler, meldeZeitpunkt);
+ Assertions.assertThat(waehleranzahlModel).hasNoNullFieldsOrProperties();
+
+ val result = unitUnderTest.fromModelToRemoteClientDTO(waehleranzahlModel);
+
+ val zoneOffset = ZoneId.systemDefault().getRules().getOffset(meldeZeitpunkt);
+ val expectedWahlbeteiligungsMeldungDTO = new WahlbeteiligungsMeldungDTO().wahlID(null).wahlbezirkID(wahlbezirkID).anzahlWaehler(anzahlWahler)
+ .meldeZeitpunkt(meldeZeitpunkt.atOffset(zoneOffset));
+ Assertions.assertThat(result).isEqualTo(expectedWahlbeteiligungsMeldungDTO);
+ }
+ }
+
+ @Nested
+ class LocalDateTimeToOffsetDateTime {
+
+ @Test
+ void should_useSummerSeasonOffset_when_mapping() {
+ val localDateTime = LocalDateTime.parse("2024-06-12T12:13:14.567");
+ val zoneID = ZoneId.of("Europe/Berlin");
+
+ val result = unitUnderTest.localDateTimeToOffsetDateTime(localDateTime, zoneID);
+
+ val expectedResult = OffsetDateTime.of(localDateTime, ZoneOffset.ofHours(2));
+ Assertions.assertThat(result).isEqualTo(expectedResult);
+ }
+
+ @Test
+ void should_useWinterSeasonOffset_when_mapping() {
+ val localDateTime = LocalDateTime.parse("2024-11-12T12:13:14.567");
+ val zoneID = ZoneId.of("Europe/Berlin");
+ val result = unitUnderTest.localDateTimeToOffsetDateTime(localDateTime, zoneID);
+
+ val expectedResult = OffsetDateTime.of(localDateTime, ZoneOffset.ofHours(1));
+ Assertions.assertThat(result).isEqualTo(expectedResult);
+ }
+ }
+}
diff --git a/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/configuration/CacheControlConfigurationTest.java b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/configuration/CacheControlConfigurationTest.java
deleted file mode 100644
index 4d6ddbc57..000000000
--- a/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/configuration/CacheControlConfigurationTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik
- * der Landeshauptstadt München, 2024
- */
-package de.muenchen.oss.wahllokalsystem.monitoringservice.configuration;
-
-import static de.muenchen.oss.wahllokalsystem.monitoringservice.TestConstants.SPRING_NO_SECURITY_PROFILE;
-import static de.muenchen.oss.wahllokalsystem.monitoringservice.TestConstants.SPRING_TEST_PROFILE;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import de.muenchen.oss.wahllokalsystem.monitoringservice.MicroServiceApplication;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.web.client.TestRestTemplate;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpMethod;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.test.context.ActiveProfiles;
-
-@SpringBootTest(
- classes = { MicroServiceApplication.class },
- webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
- properties = {
- "spring.datasource.url=jdbc:h2:mem:testexample;DB_CLOSE_ON_EXIT=FALSE",
- "refarch.gracefulshutdown.pre-wait-seconds=0"
- }
-)
-@ActiveProfiles(profiles = { SPRING_TEST_PROFILE, SPRING_NO_SECURITY_PROFILE })
-class CacheControlConfigurationTest {
-
- private static final String ENTITY_ENDPOINT_URL = "/theEntities";
-
- private static final String EXPECTED_CACHE_CONTROL_HEADER_VALUES = "no-cache, no-store, must-revalidate";
-
- @Autowired
- private TestRestTemplate testRestTemplate;
-
- @Test
- @Disabled
- void testForCacheControlHeadersForEntityEndpoint() {
- ResponseEntity response = testRestTemplate.exchange(ENTITY_ENDPOINT_URL, HttpMethod.GET, null, String.class);
- assertEquals(HttpStatus.OK, response.getStatusCode());
- assertTrue(response.getHeaders().containsKey(HttpHeaders.CACHE_CONTROL));
- assertEquals(EXPECTED_CACHE_CONTROL_HEADER_VALUES, response.getHeaders().getCacheControl());
- }
-
-}
diff --git a/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/configuration/SecurityConfigurationTest.java b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/configuration/SecurityConfigurationTest.java
index 1f6ff4d6b..10cf64d31 100644
--- a/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/configuration/SecurityConfigurationTest.java
+++ b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/configuration/SecurityConfigurationTest.java
@@ -1,15 +1,26 @@
package de.muenchen.oss.wahllokalsystem.monitoringservice.configuration;
import static de.muenchen.oss.wahllokalsystem.monitoringservice.TestConstants.SPRING_TEST_PROFILE;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+import com.fasterxml.jackson.databind.ObjectMapper;
import de.muenchen.oss.wahllokalsystem.monitoringservice.MicroServiceApplication;
+import de.muenchen.oss.wahllokalsystem.monitoringservice.rest.waehleranzahl.WaehleranzahlDTO;
+import de.muenchen.oss.wahllokalsystem.monitoringservice.service.waehleranzahl.WaehleranzahlService;
+import lombok.val;
+import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.actuate.observability.AutoConfigureObservability;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.MediaType;
+import org.springframework.security.test.context.support.WithAnonymousUser;
+import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc;
@@ -19,9 +30,15 @@
@ActiveProfiles(profiles = { SPRING_TEST_PROFILE })
class SecurityConfigurationTest {
+ @MockBean
+ WaehleranzahlService waehleranzahlService;
+
@Autowired
MockMvc api;
+ @Autowired
+ ObjectMapper objectMapper;
+
@Test
void accessSecuredResourceRootThenUnauthorized() throws Exception {
api.perform(get("/"))
@@ -64,4 +81,35 @@ void accessUnsecuredResourceSwaggerUiThenOk() throws Exception {
.andExpect(status().isOk());
}
+ @Nested
+ class Waehleranzahl {
+
+ @Test
+ @WithAnonymousUser
+ void should_return401Unauthorized_when_getWithUnauthorizedAnonymousUser() throws Exception {
+ api.perform(get("/businessActions/wahlbeteiligung/wahlID/wahlbezirkID")).andExpect(status().isUnauthorized());
+ }
+
+ @Test
+ @WithMockUser
+ void should_return204NoContent_when_getWithAuthorizedMockUser() throws Exception {
+ api.perform(get("/businessActions/wahlbeteiligung/wahlID/wahlbezirkID")).andExpect(status().isNoContent());
+ }
+
+ @Test
+ @WithAnonymousUser
+ void should_return401Unauthorized_when_postWithUnauthorizedAnonymousUser() throws Exception {
+ api.perform(post("/businessActions/wahlbeteiligung/wahlID/wahlbezirkID").with(csrf())).andExpect(status().isUnauthorized());
+ }
+
+ @Test
+ @WithMockUser
+ void should_return200OK_when_postWithAuthorizedMockUser() throws Exception {
+ val requestBody = new WaehleranzahlDTO(null, null);
+ val request = post("/businessActions/wahlbeteiligung/wahlID/wahlbezirkID").with(csrf()).contentType(MediaType.APPLICATION_JSON).content(
+ objectMapper.writeValueAsString(requestBody));
+
+ api.perform(request).andExpect(status().isOk());
+ }
+ }
}
diff --git a/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/configuration/UnicodeConfigurationTest.java b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/configuration/UnicodeConfigurationTest.java
deleted file mode 100644
index 119a8b609..000000000
--- a/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/configuration/UnicodeConfigurationTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik
- * der Landeshauptstadt München, 2024
- */
-package de.muenchen.oss.wahllokalsystem.monitoringservice.configuration;
-
-import static de.muenchen.oss.wahllokalsystem.monitoringservice.TestConstants.SPRING_NO_SECURITY_PROFILE;
-import static de.muenchen.oss.wahllokalsystem.monitoringservice.TestConstants.SPRING_TEST_PROFILE;
-import static de.muenchen.oss.wahllokalsystem.monitoringservice.TestConstants.TheEntityDto;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import de.muenchen.oss.wahllokalsystem.monitoringservice.MicroServiceApplication;
-import de.muenchen.oss.wahllokalsystem.monitoringservice.domain.TheEntity;
-import de.muenchen.oss.wahllokalsystem.monitoringservice.rest.TheEntityRepository;
-import java.net.URI;
-import java.util.UUID;
-import org.apache.commons.lang3.StringUtils;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.web.client.TestRestTemplate;
-import org.springframework.test.context.ActiveProfiles;
-
-@SpringBootTest(
- classes = { MicroServiceApplication.class },
- webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
- properties = {
- "spring.datasource.url=jdbc:h2:mem:testexample;DB_CLOSE_ON_EXIT=FALSE",
- "refarch.gracefulshutdown.pre-wait-seconds=0"
- }
-)
-@ActiveProfiles(profiles = { SPRING_TEST_PROFILE, SPRING_NO_SECURITY_PROFILE })
-class UnicodeConfigurationTest {
-
- private static final String ENTITY_ENDPOINT_URL = "/theEntities";
-
- /**
- * Decomposed string: String "Ä-é" represented with unicode letters "A◌̈-e◌́"
- */
- private static final String TEXT_ATTRIBUTE_DECOMPOSED = "\u0041\u0308-\u0065\u0301";
-
- /**
- * Composed string: String "Ä-é" represented with unicode letters "Ä-é".
- */
- private static final String TEXT_ATTRIBUTE_COMPOSED = "\u00c4-\u00e9";
-
- @Autowired
- private TestRestTemplate testRestTemplate;
-
- @Autowired
- private TheEntityRepository theEntityRepository;
-
- @Test
- @Disabled
- void testForNfcNormalization() {
- // Persist entity with decomposed string.
- final TheEntityDto theEntityDto = new TheEntityDto();
- theEntityDto.setTextAttribute(TEXT_ATTRIBUTE_DECOMPOSED);
- assertEquals(TEXT_ATTRIBUTE_DECOMPOSED.length(), theEntityDto.getTextAttribute().length());
- final TheEntityDto response = testRestTemplate.postForEntity(URI.create(ENTITY_ENDPOINT_URL), theEntityDto, TheEntityDto.class).getBody();
-
- // Check whether response contains a composed string.
- assertEquals(TEXT_ATTRIBUTE_COMPOSED, response.getTextAttribute());
- assertEquals(TEXT_ATTRIBUTE_COMPOSED.length(), response.getTextAttribute().length());
-
- // Extract uuid from self link.
- final UUID uuid = UUID.fromString(StringUtils.substringAfterLast(response.getRequiredLink("self").getHref(), "/"));
-
- // Check persisted entity contains a composed string via JPA repository.
- final TheEntity theEntity = theEntityRepository.findById(uuid).orElse(null);
- assertEquals(TEXT_ATTRIBUTE_COMPOSED, theEntity.getTextAttribute());
- assertEquals(TEXT_ATTRIBUTE_COMPOSED.length(), theEntity.getTextAttribute().length());
- }
-
-}
diff --git a/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/rest/TheEntityRepositoryTest.java b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/rest/TheEntityRepositoryTest.java
deleted file mode 100644
index b301a4131..000000000
--- a/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/rest/TheEntityRepositoryTest.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik
- * der Landeshauptstadt München, 2024
- */
-package de.muenchen.oss.wahllokalsystem.monitoringservice.rest;
-
-import static de.muenchen.oss.wahllokalsystem.monitoringservice.TestConstants.SPRING_NO_SECURITY_PROFILE;
-import static de.muenchen.oss.wahllokalsystem.monitoringservice.TestConstants.SPRING_TEST_PROFILE;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-
-import de.muenchen.oss.wahllokalsystem.monitoringservice.MicroServiceApplication;
-import de.muenchen.oss.wahllokalsystem.monitoringservice.domain.TheEntity;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.ActiveProfiles;
-import org.springframework.transaction.annotation.Propagation;
-import org.springframework.transaction.annotation.Transactional;
-
-@SpringBootTest(
- classes = { MicroServiceApplication.class },
- webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
- properties = {
- "spring.datasource.url=jdbc:h2:mem:wls;DB_CLOSE_ON_EXIT=FALSE",
- "refarch.gracefulshutdown.pre-wait-seconds=0"
- }
-)
-@ActiveProfiles(profiles = { SPRING_TEST_PROFILE, SPRING_NO_SECURITY_PROFILE })
-class TheEntityRepositoryTest {
-
- @Autowired
- private TheEntityRepository repository;
-
- @Test
- @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Exception.class)
- void testSave() {
-
- // Implement your logic here by replacing and/or extending the code
-
- // initialize
- TheEntity original = new TheEntity();
- original.setTextAttribute("test");
-
- // persist
- original = repository.save(original);
-
- // check
- TheEntity persisted = repository.findById(original.getId()).orElse(null);
- assertNotNull(persisted);
- assertEquals(original, persisted);
-
- }
-
-}
diff --git a/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/rest/waehleranzahl/WaehleranzahlControllerIntegrationTest.java b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/rest/waehleranzahl/WaehleranzahlControllerIntegrationTest.java
new file mode 100644
index 000000000..e73bf7bb7
--- /dev/null
+++ b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/rest/waehleranzahl/WaehleranzahlControllerIntegrationTest.java
@@ -0,0 +1,164 @@
+package de.muenchen.oss.wahllokalsystem.monitoringservice.rest.waehleranzahl;
+
+import static de.muenchen.oss.wahllokalsystem.monitoringservice.TestConstants.SPRING_NO_SECURITY_PROFILE;
+import static de.muenchen.oss.wahllokalsystem.monitoringservice.TestConstants.SPRING_TEST_PROFILE;
+import static org.mockito.ArgumentMatchers.any;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import de.muenchen.oss.wahllokalsystem.monitoringservice.MicroServiceApplication;
+import de.muenchen.oss.wahllokalsystem.monitoringservice.domain.waehleranzahl.Waehleranzahl;
+import de.muenchen.oss.wahllokalsystem.monitoringservice.domain.waehleranzahl.WaehleranzahlRepository;
+import de.muenchen.oss.wahllokalsystem.monitoringservice.exception.ExceptionConstants;
+import de.muenchen.oss.wahllokalsystem.monitoringservice.service.waehleranzahl.WaehleranzahlModelMapper;
+import de.muenchen.oss.wahllokalsystem.wls.common.exception.rest.model.WlsExceptionCategory;
+import de.muenchen.oss.wahllokalsystem.wls.common.exception.rest.model.WlsExceptionDTO;
+import de.muenchen.oss.wahllokalsystem.wls.common.security.domain.BezirkUndWahlID;
+import java.time.LocalDateTime;
+import lombok.val;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.SpyBean;
+import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.RequestBuilder;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+
+@SpringBootTest(classes = MicroServiceApplication.class, webEnvironment = SpringBootTest.WebEnvironment.MOCK)
+@AutoConfigureMockMvc
+@AutoConfigureWireMock
+@ActiveProfiles(profiles = { SPRING_TEST_PROFILE, SPRING_NO_SECURITY_PROFILE })
+public class WaehleranzahlControllerIntegrationTest {
+
+ @Value("${service.info.oid}")
+ String serviceID;
+
+ @Autowired
+ ObjectMapper objectMapper;
+
+ @SpyBean
+ WaehleranzahlRepository wahleranzahlRepository;
+
+ @Autowired
+ WaehleranzahlDTOMapper waehleranzahlDTOMapper;
+
+ @Autowired
+ WaehleranzahlModelMapper waehleranzahlModelMapper;
+
+ @Autowired
+ MockMvc api;
+
+ @Autowired
+ WaehleranzahlRepository waehleranzahlRepository;
+
+ @AfterEach
+ void tearDown() {
+ waehleranzahlRepository.deleteAll();
+ }
+
+ @Nested
+ class GetWahlbeteiligung {
+
+ @Test
+ void should_returnEmptyResponse_when_noDataFound() throws Exception {
+ val wahlID = "wahlID01";
+ val wahlbezirkID = "wahlbezirkID01";
+ val request = MockMvcRequestBuilders.get("/businessActions/wahlbeteiligung/" + wahlID + "/" + wahlbezirkID);
+
+ val response = api.perform(request).andExpect(status().isNoContent()).andReturn();
+
+ Assertions.assertThat(response.getResponse().getContentAsString()).isEmpty();
+ }
+
+ @Test
+ void should_returnOkAndData_when_dataFound() throws Exception {
+ val wahlID = "wahlID01";
+ val wahlbezirkID = "wahlbezirkID01";
+ val bezirkUndWahlID = new BezirkUndWahlID(wahlID, wahlbezirkID);
+ val anzahlWaehler = 99;
+ val uhrzeit = LocalDateTime.parse("2024-09-13T12:11:21.343");
+
+ val waehleranzahlToFind = new Waehleranzahl(bezirkUndWahlID, anzahlWaehler, uhrzeit);
+ waehleranzahlRepository.save(waehleranzahlToFind);
+
+ val request = MockMvcRequestBuilders.get("/businessActions/wahlbeteiligung/" + wahlID + "/" + wahlbezirkID);
+
+ val response = api.perform(request).andExpect(status().isOk()).andReturn();
+ val responseBodyAsDTO = objectMapper.readValue(response.getResponse().getContentAsString(), WaehleranzahlDTO.class);
+
+ val expectedResponseBody = waehleranzahlDTOMapper.toDTO(waehleranzahlModelMapper.toModel(waehleranzahlToFind));
+ Assertions.assertThat(responseBodyAsDTO).isEqualTo(expectedResponseBody);
+ }
+
+ @Nested
+ class PostWahlbeteiligung {
+
+ @Test
+ void should_overwriteExistingData_when_newDataIsStoredWithSameID() throws Exception {
+ val wahlID = "wahlID01";
+ val wahlbezirkID = "wahlbezirkID01";
+ val bezirkUndWahlID = new BezirkUndWahlID(wahlID, wahlbezirkID);
+ val anzahlWaehler_1 = 99L;
+ val uhrzeit_1 = LocalDateTime.parse("2024-09-13T12:11:21.343");
+
+ // store data with bezirkUndWahlID
+ val waehleranzahlToFind = new Waehleranzahl(bezirkUndWahlID, anzahlWaehler_1, uhrzeit_1);
+ waehleranzahlRepository.save(waehleranzahlToFind);
+
+ // Overwrite existing data with same bezirkUndWahlID
+ val anzahlWaehler_2 = 55L;
+ val uhrzeit_2 = LocalDateTime.parse("2024-09-13T12:11:21.666");
+ val waehleranzahlDTO_2 = new WaehleranzahlDTO(anzahlWaehler_2, uhrzeit_2);
+
+ val request_2 = buildPostRequest(wahlID, wahlbezirkID, waehleranzahlDTO_2);
+ api.perform(request_2).andExpect(status().isOk()).andReturn();
+
+ val waehleranzahlFromRepo_2 = waehleranzahlRepository.findById(bezirkUndWahlID).get();
+ val expectedWaehleranzahl_2 = waehleranzahlModelMapper.toEntity(waehleranzahlDTOMapper.toSetModel(bezirkUndWahlID, waehleranzahlDTO_2));
+
+ Assertions.assertThat(waehleranzahlFromRepo_2).usingRecursiveComparison().isEqualTo(expectedWaehleranzahl_2);
+ }
+ }
+
+ @Test
+ void should_throwTechnischeWlsException_when_saveInDBFails() throws Exception {
+ val wahlID = "_ ";
+ val wahlbezirkID = "wahlbezirkID01";
+ val anzahlWaehler = 99L;
+ val uhrzeit = LocalDateTime.parse("2024-09-13T12:11:21.343");
+ val waehleranzahlDTO = new WaehleranzahlDTO(anzahlWaehler, uhrzeit);
+
+ val request = MockMvcRequestBuilders.post("/businessActions/wahlbeteiligung/" + wahlID + "/" + wahlbezirkID).with(csrf())
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(
+ objectMapper.writeValueAsString(waehleranzahlDTO));
+
+ Mockito.doThrow(new RuntimeException("DB-Error")).when(wahleranzahlRepository).save(any());
+
+ val response = api.perform(request).andExpect(status().isInternalServerError()).andReturn();
+
+ val responseBodyAsWlsExceptionDTO = objectMapper.readValue(response.getResponse().getContentAsByteArray(), WlsExceptionDTO.class);
+
+ val expectedWlsExceptionDTO = new WlsExceptionDTO(WlsExceptionCategory.T, ExceptionConstants.POSTWAHLBETEILIGUNG_UNSAVEABLE.code(),
+ serviceID, ExceptionConstants.POSTWAHLBETEILIGUNG_UNSAVEABLE.message());
+
+ Assertions.assertThat(responseBodyAsWlsExceptionDTO).isEqualTo(expectedWlsExceptionDTO);
+ }
+
+ private RequestBuilder buildPostRequest(final String wahlID, final String wahlbezirkID, final WaehleranzahlDTO requestBody) throws Exception {
+ return post("/businessActions/wahlbeteiligung/" + wahlID + "/" + wahlbezirkID).with(csrf()).contentType(MediaType.APPLICATION_JSON).content(
+ objectMapper.writeValueAsString(requestBody));
+ }
+ }
+}
diff --git a/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/rest/waehleranzahl/WaehleranzahlControllerTest.java b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/rest/waehleranzahl/WaehleranzahlControllerTest.java
new file mode 100644
index 000000000..ee08ff25f
--- /dev/null
+++ b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/rest/waehleranzahl/WaehleranzahlControllerTest.java
@@ -0,0 +1,88 @@
+package de.muenchen.oss.wahllokalsystem.monitoringservice.rest.waehleranzahl;
+
+import de.muenchen.oss.wahllokalsystem.monitoringservice.service.waehleranzahl.WaehleranzahlModel;
+import de.muenchen.oss.wahllokalsystem.monitoringservice.service.waehleranzahl.WaehleranzahlService;
+import de.muenchen.oss.wahllokalsystem.wls.common.security.domain.BezirkUndWahlID;
+import java.time.LocalDateTime;
+import java.util.Optional;
+import lombok.val;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.http.HttpStatus;
+
+@ExtendWith(MockitoExtension.class)
+public class WaehleranzahlControllerTest {
+
+ @Mock
+ WaehleranzahlService waehleranzahlService;
+
+ @Mock
+ WaehleranzahlDTOMapper waehleranzahlDTOMapper;
+
+ @InjectMocks
+ WaehleranzahlController unitUnderTest;
+
+ @Nested
+ class GetWahlbeteiligung {
+
+ @Test
+ void should_returnHttp200AndData_when_dataIsFound() {
+
+ val wahlID = "wahlID01";
+ val wahlbezirkID = "wahlbezirkID01";
+ val bezirkUndWahlID = new BezirkUndWahlID(wahlID, wahlbezirkID);
+ val uhrzeit = LocalDateTime.now();
+
+ val mockedServiceModel = new WaehleranzahlModel(null, 0, null);
+ val mockedMappedServiceDTO = new WaehleranzahlDTO(99L, uhrzeit);
+
+ Mockito.when(waehleranzahlService.getWahlbeteiligung(bezirkUndWahlID)).thenReturn(Optional.of(mockedServiceModel));
+ Mockito.when(waehleranzahlDTOMapper.toDTO(mockedServiceModel)).thenReturn(mockedMappedServiceDTO);
+
+ val result = unitUnderTest.getWahlbeteiligung(wahlID, wahlbezirkID);
+
+ Assertions.assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK);
+ Assertions.assertThat(result.getBody()).isSameAs(mockedMappedServiceDTO);
+ }
+
+ @Test
+ void should_returnHttp204AndBodyIsNull_when_serviceReturnsNoData() {
+ val wahlID = "wahlID01";
+ val wahlbezirkID = "wahlbezirkID01";
+ val bezirkUndWahlID = new BezirkUndWahlID(wahlID, wahlbezirkID);
+
+ Mockito.when(waehleranzahlService.getWahlbeteiligung(bezirkUndWahlID)).thenReturn(Optional.empty());
+
+ val result = unitUnderTest.getWahlbeteiligung(wahlID, wahlbezirkID);
+
+ Assertions.assertThat(result.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
+ Assertions.assertThat(result.getBody()).isNull();
+ }
+ }
+
+ @Nested
+ class PostWahlbeteiligung {
+
+ @Test
+ void should_notThrowException_when_serviceIsCalled() {
+ val wahlID = "wahlID01";
+ val wahlbezirkID = "wahlbezirkID01";
+ val bezirkUndWahlID = new BezirkUndWahlID(wahlID, wahlbezirkID);
+
+ val requestBody = Mockito.mock(WaehleranzahlDTO.class);
+ val mockedMappedRequest = Mockito.mock(WaehleranzahlModel.class);
+
+ Mockito.when(waehleranzahlDTOMapper.toSetModel(bezirkUndWahlID, requestBody)).thenReturn(mockedMappedRequest);
+
+ unitUnderTest.postWahlbeteiligung(wahlbezirkID, wahlID, requestBody);
+
+ Mockito.verify(waehleranzahlService).postWahlbeteiligung(mockedMappedRequest);
+ }
+ }
+}
diff --git a/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/rest/waehleranzahl/WaehleranzahlDTOMapperTest.java b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/rest/waehleranzahl/WaehleranzahlDTOMapperTest.java
new file mode 100644
index 000000000..7605b5806
--- /dev/null
+++ b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/rest/waehleranzahl/WaehleranzahlDTOMapperTest.java
@@ -0,0 +1,65 @@
+package de.muenchen.oss.wahllokalsystem.monitoringservice.rest.waehleranzahl;
+
+import de.muenchen.oss.wahllokalsystem.monitoringservice.service.waehleranzahl.WaehleranzahlModel;
+import de.muenchen.oss.wahllokalsystem.wls.common.security.domain.BezirkUndWahlID;
+import java.time.LocalDateTime;
+import lombok.val;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mapstruct.factory.Mappers;
+
+class WaehleranzahlDTOMapperTest {
+
+ private final WaehleranzahlDTOMapper unitUnderTest = Mappers.getMapper(WaehleranzahlDTOMapper.class);
+
+ @Nested
+ class ToDTO {
+
+ @Test
+ void should_returnNull_when_modelIsNull() {
+ Assertions.assertThat(unitUnderTest.toDTO(null)).isNull();
+ }
+
+ @Test
+ void should_mapModelToDto_when_ModelIsNotNull() {
+ String wahlID = "wahlID01";
+ String wahlbezirkID = "wahlbezirkID01";
+ long anzahlWaehler = 99L;
+ LocalDateTime uhrzeit = LocalDateTime.now();
+ BezirkUndWahlID bezirkUndWahlID = new BezirkUndWahlID(wahlID, wahlbezirkID);
+
+ val modelInput = new WaehleranzahlModel(bezirkUndWahlID, anzahlWaehler, uhrzeit);
+ val dtoExpected = new WaehleranzahlDTO(anzahlWaehler, uhrzeit);
+
+ val result = unitUnderTest.toDTO(modelInput);
+ Assertions.assertThat(result).isEqualTo(dtoExpected);
+ }
+
+ }
+
+ @Nested
+ class ToSetModel {
+
+ @Test
+ void should_returnNull_when_dtoIsNull() {
+ Assertions.assertThat(unitUnderTest.toSetModel(null, null)).isNull();
+ }
+
+ @Test
+ void should_mapDtoToModel_when_DtoIsNotNull() {
+ String wahlID = "wahlID01";
+ String wahlbezirkID = "wahlbezirkID01";
+ long anzahlWaehler = 99L;
+ LocalDateTime uhrzeit = LocalDateTime.now();
+ BezirkUndWahlID bezirkUndWahlID = new BezirkUndWahlID(wahlID, wahlbezirkID);
+
+ val dtoInput = new WaehleranzahlDTO(anzahlWaehler, uhrzeit);
+ val modelExpected = new WaehleranzahlModel(bezirkUndWahlID, anzahlWaehler, uhrzeit);
+
+ val result = unitUnderTest.toSetModel(bezirkUndWahlID, dtoInput);
+ Assertions.assertThat(result).isEqualTo(modelExpected);
+ }
+
+ }
+}
diff --git a/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlModelMapperTest.java b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlModelMapperTest.java
new file mode 100644
index 000000000..0e587b890
--- /dev/null
+++ b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlModelMapperTest.java
@@ -0,0 +1,46 @@
+package de.muenchen.oss.wahllokalsystem.monitoringservice.service.waehleranzahl;
+
+import de.muenchen.oss.wahllokalsystem.monitoringservice.domain.waehleranzahl.Waehleranzahl;
+import de.muenchen.oss.wahllokalsystem.wls.common.security.domain.BezirkUndWahlID;
+import java.time.LocalDateTime;
+import lombok.val;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.mapstruct.factory.Mappers;
+
+class WaehleranzahlModelMapperTest {
+
+ private final WaehleranzahlModelMapper unitUnderTest = Mappers.getMapper(WaehleranzahlModelMapper.class);
+
+ @Test
+ void should_returnEqualWaehleranzahlModel_when_waehleranzahlIsMapped() {
+ val wahlID = "wahlID01";
+ val wahlbezirkID = "wahlbezirkID01";
+ BezirkUndWahlID bezirkUndWahlID = new BezirkUndWahlID(wahlID, wahlbezirkID);
+ val anzahlWaehler = 99;
+ LocalDateTime uhrzeit = LocalDateTime.now();
+ val waehleranzahlEntity = new Waehleranzahl(bezirkUndWahlID, anzahlWaehler, uhrzeit);
+
+ val waehleranzahlModel = unitUnderTest.toModel(waehleranzahlEntity);
+
+ val expectedResult = new WaehleranzahlModel(bezirkUndWahlID, anzahlWaehler, uhrzeit);
+
+ Assertions.assertThat(waehleranzahlModel).isEqualTo(expectedResult);
+ }
+
+ @Test
+ void should_returnEqualWaehleranzahl_when_waehleranzahlModelIsMapped() {
+ val wahlID = "wahlID01";
+ val wahlbezirkID = "wahlbezirkID01";
+ BezirkUndWahlID bezirkUndWahlID = new BezirkUndWahlID(wahlID, wahlbezirkID);
+ val anzahlWaehler = 99;
+ LocalDateTime uhrzeit = LocalDateTime.now();
+ val waehleranzahlModel = new WaehleranzahlModel(bezirkUndWahlID, anzahlWaehler, uhrzeit);
+
+ val waehleranzahlEntity = unitUnderTest.toEntity(waehleranzahlModel);
+
+ val expectedResult = new Waehleranzahl(bezirkUndWahlID, anzahlWaehler, uhrzeit);
+
+ Assertions.assertThat(waehleranzahlEntity).isEqualTo(expectedResult);
+ }
+}
diff --git a/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlServiceSecurityTest.java b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlServiceSecurityTest.java
new file mode 100644
index 000000000..dd59ec9d2
--- /dev/null
+++ b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlServiceSecurityTest.java
@@ -0,0 +1,149 @@
+package de.muenchen.oss.wahllokalsystem.monitoringservice.service.waehleranzahl;
+
+import static org.springframework.security.core.context.SecurityContextHolder.clearContext;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.github.tomakehurst.wiremock.client.WireMock;
+import de.muenchen.oss.wahllokalsystem.monitoringservice.MicroServiceApplication;
+import de.muenchen.oss.wahllokalsystem.monitoringservice.TestConstants;
+import de.muenchen.oss.wahllokalsystem.monitoringservice.domain.waehleranzahl.Waehleranzahl;
+import de.muenchen.oss.wahllokalsystem.monitoringservice.domain.waehleranzahl.WaehleranzahlRepository;
+import de.muenchen.oss.wahllokalsystem.monitoringservice.rest.waehleranzahl.WaehleranzahlDTOMapper;
+import de.muenchen.oss.wahllokalsystem.monitoringservice.utils.Authorities;
+import de.muenchen.oss.wahllokalsystem.wls.common.exception.TechnischeWlsException;
+import de.muenchen.oss.wahllokalsystem.wls.common.security.domain.BezirkUndWahlID;
+import de.muenchen.oss.wahllokalsystem.wls.common.testing.SecurityUtils;
+import java.time.LocalDateTime;
+import java.util.stream.Stream;
+import lombok.val;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.aggregator.ArgumentsAccessor;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.test.context.ActiveProfiles;
+
+@SpringBootTest(classes = MicroServiceApplication.class)
+@ActiveProfiles({ TestConstants.SPRING_TEST_PROFILE })
+@AutoConfigureWireMock
+public class WaehleranzahlServiceSecurityTest {
+
+ @Autowired
+ WaehleranzahlService waehleranzahlService;
+
+ @Autowired
+ WaehleranzahlRepository waehleranzahlRepository;
+
+ @Autowired
+ WaehleranzahlDTOMapper waehleranzahlDTOMapper;
+
+ @Autowired
+ ObjectMapper objectMapper;
+
+ @MockBean
+ WaehleranzahlValidator waehleranzahlValidator;
+
+ @BeforeEach
+ void setup() {
+ clearContext();
+ }
+
+ @AfterEach
+ void tearDown() {
+ SecurityUtils.runWith(Authorities.REPOSITORY_DELETE_WAEHLERANZAHL);
+ waehleranzahlRepository.deleteAll();
+ }
+
+ @Nested
+ class GetWahlbeteiligung {
+
+ @Test
+ void should_grantAccessAndThrowNoException_when_authoritiesAreValid() {
+ BezirkUndWahlID bezirkUndWahlID = new BezirkUndWahlID("wahlID01", "wahlbezirkID01");
+ SecurityUtils.runWith(Authorities.REPOSITORY_WRITE_WAEHLERANZAHL);
+ waehleranzahlRepository.save(new Waehleranzahl(bezirkUndWahlID, 99, LocalDateTime.now()));
+
+ SecurityUtils.runWith(Authorities.ALL_AUTHORITIES_GET_WAEHLERANZAHL);
+
+ Assertions.assertThatNoException().isThrownBy(() -> waehleranzahlService.getWahlbeteiligung(bezirkUndWahlID));
+ }
+
+ @ParameterizedTest(name = "{index} - {1} missing")
+ @MethodSource("getMissingAuthoritiesVariations")
+ void should_failWithAccessDeniedException_when_anyAuthorityIsMissing(final ArgumentsAccessor argumentsAccessor) {
+ SecurityUtils.runWith(argumentsAccessor.get(0, String[].class));
+ BezirkUndWahlID bezirkUndWahlID = new BezirkUndWahlID("wahlID01", "wahlbezirkID01");
+ Assertions.assertThatThrownBy(() -> waehleranzahlService.getWahlbeteiligung(bezirkUndWahlID)).isInstanceOf(AccessDeniedException.class);
+ }
+
+ private static Stream getMissingAuthoritiesVariations() {
+ return SecurityUtils.buildArgumentsForMissingAuthoritiesVariations(Authorities.ALL_AUTHORITIES_GET_WAEHLERANZAHL);
+ }
+ }
+
+ @Nested
+ class PostWahlbeteiligung {
+
+ @Test
+ void should_grantAccessAndThrowNoException_when_authoritiesAreValid() throws Exception {
+ SecurityUtils.runWith(Authorities.ALL_AUTHORITIES_SET_WAEHLERANZAHL);
+ String wahlID = "wahlID01";
+ String wahlbezirkID = "wahlbezirkID01";
+ BezirkUndWahlID bezirkUndWahlID = new BezirkUndWahlID(wahlID, wahlbezirkID);
+ val waehleranzahlToSave = new WaehleranzahlModel(bezirkUndWahlID, 99L, LocalDateTime.now());
+
+ val waehleranzahlDTO = waehleranzahlDTOMapper.toDTO(waehleranzahlToSave);
+ WireMock.stubFor(WireMock.post("/wahlbeteiligung")
+ .willReturn(WireMock.aResponse().withHeader("Content-Type", "application/json").withStatus(HttpStatus.OK.value())
+ .withBody(objectMapper.writeValueAsBytes(waehleranzahlDTO))));
+
+ Assertions.assertThatNoException().isThrownBy(() -> waehleranzahlService.postWahlbeteiligung(waehleranzahlToSave));
+ }
+
+ @Test
+ void should_failWithAccessDeniedException_when_serviceAuthorityIsMissing() throws Exception {
+ SecurityUtils.runWith(Authorities.REPOSITORY_WRITE_WAEHLERANZAHL);
+
+ String wahlID = "wahlID01";
+ String wahlbezirkID = "wahlbezirkID01";
+ BezirkUndWahlID bezirkUndWahlID = new BezirkUndWahlID(wahlID, wahlbezirkID);
+ val waehleranzahlToSave = new WaehleranzahlModel(bezirkUndWahlID, 99L, LocalDateTime.now());
+
+ val waehleranzahlDTO = waehleranzahlDTOMapper.toDTO(waehleranzahlToSave);
+ WireMock.stubFor(WireMock.post("/wahlbeteiligung")
+ .willReturn(WireMock.aResponse().withHeader("Content-Type", "application/json").withStatus(HttpStatus.OK.value())
+ .withBody(objectMapper.writeValueAsBytes(waehleranzahlDTO))));
+
+ Assertions.assertThatThrownBy(() -> waehleranzahlService.postWahlbeteiligung(waehleranzahlToSave)).isInstanceOf(AccessDeniedException.class);
+ }
+
+ @Test
+ void should_failWithTechnischeWlsException_when_repoAuthorityIsMissing() throws Exception {
+ SecurityUtils.runWith(Authorities.SERVICE_POST_WAEHLERANZAHL);
+
+ String wahlID = "wahlID01";
+ String wahlbezirkID = "wahlbezirkID01";
+ BezirkUndWahlID bezirkUndWahlID = new BezirkUndWahlID(wahlID, wahlbezirkID);
+ val waehleranzahlToSave = new WaehleranzahlModel(bezirkUndWahlID, 99L, LocalDateTime.now());
+
+ val waehleranzahlDTO = waehleranzahlDTOMapper.toDTO(waehleranzahlToSave);
+ WireMock.stubFor(WireMock.post("/wahlbeteiligung")
+ .willReturn(WireMock.aResponse().withHeader("Content-Type", "application/json").withStatus(HttpStatus.OK.value())
+ .withBody(objectMapper.writeValueAsBytes(waehleranzahlDTO))));
+
+ Assertions.assertThatThrownBy(() -> waehleranzahlService.postWahlbeteiligung(waehleranzahlToSave)).isInstanceOf(TechnischeWlsException.class);
+ }
+
+ }
+
+}
diff --git a/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlServiceTest.java b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlServiceTest.java
new file mode 100644
index 000000000..9be7aeb77
--- /dev/null
+++ b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlServiceTest.java
@@ -0,0 +1,77 @@
+package de.muenchen.oss.wahllokalsystem.monitoringservice.service.waehleranzahl;
+
+import de.muenchen.oss.wahllokalsystem.monitoringservice.domain.waehleranzahl.Waehleranzahl;
+import de.muenchen.oss.wahllokalsystem.monitoringservice.domain.waehleranzahl.WaehleranzahlRepository;
+import de.muenchen.oss.wahllokalsystem.wls.common.security.domain.BezirkUndWahlID;
+import java.time.LocalDateTime;
+import java.util.Optional;
+import lombok.val;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+@ExtendWith(MockitoExtension.class)
+public class WaehleranzahlServiceTest {
+
+ @Mock
+ WaehleranzahlRepository waehleranzahlRepository;
+ @Mock
+ WaehleranzahlModelMapper waehleranzahlModelMapper;
+ @Mock
+ WaehleranzahlValidator waehleranzahlValidator;
+ @Mock
+ WaehleranzahlClient waehleranzahlClient;
+
+ @InjectMocks
+ WaehleranzahlService unitUnderTest;
+
+ @Nested
+ class GetWahlbeteiligung {
+
+ @Test
+ void should_returnRepoData_when_repoDataFound() {
+ BezirkUndWahlID bezirkUndWahlID = new BezirkUndWahlID("wahlID01", "wahlbezirkID01");
+
+ val mockedRepoResponse = new Waehleranzahl();
+ val mockedMappedRepoResponse = new WaehleranzahlModel(bezirkUndWahlID, 99L, LocalDateTime.now());
+ Mockito.doNothing().when(waehleranzahlValidator).validWahlIdUndWahlbezirkIDOrThrow(bezirkUndWahlID);
+
+ Mockito.when(waehleranzahlRepository.findById(bezirkUndWahlID)).thenReturn(Optional.of(mockedRepoResponse));
+ Mockito.when(waehleranzahlModelMapper.toModel(mockedRepoResponse)).thenReturn(mockedMappedRepoResponse);
+
+ Assertions.assertThat(unitUnderTest.getWahlbeteiligung(bezirkUndWahlID).get()).isSameAs(mockedMappedRepoResponse);
+ }
+
+ @Test
+ void should_returnEmptyResult_when_repoDataNotFound() {
+ BezirkUndWahlID bezirkUndWahlID = new BezirkUndWahlID("wahlID01", "wahlbezirkID01");
+
+ Mockito.when(waehleranzahlRepository.findById(bezirkUndWahlID)).thenReturn(Optional.empty());
+
+ val result = unitUnderTest.getWahlbeteiligung(bezirkUndWahlID);
+ Assertions.assertThat(result).isEmpty();
+ }
+ }
+
+ @Nested
+ class PostWahlbeteiligung {
+
+ @Test
+ void should_notThrowExceptionAndSaveDataInRepo_when_modelIsGiven() {
+ val waehleranzahlSetModel = WaehleranzahlModel.builder().build();
+ val mockedKonfigurationEntity = new Waehleranzahl();
+
+ Mockito.when(waehleranzahlModelMapper.toEntity(waehleranzahlSetModel)).thenReturn(mockedKonfigurationEntity);
+
+ Assertions.assertThatNoException().isThrownBy(() -> unitUnderTest.postWahlbeteiligung(waehleranzahlSetModel));
+
+ Mockito.verify(waehleranzahlClient).postWahlbeteiligung(waehleranzahlSetModel);
+ Mockito.verify(waehleranzahlRepository).save(mockedKonfigurationEntity);
+ }
+ }
+}
diff --git a/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlValidatorTest.java b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlValidatorTest.java
new file mode 100644
index 000000000..80f8bd84a
--- /dev/null
+++ b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/service/waehleranzahl/WaehleranzahlValidatorTest.java
@@ -0,0 +1,75 @@
+package de.muenchen.oss.wahllokalsystem.monitoringservice.service.waehleranzahl;
+
+import de.muenchen.oss.wahllokalsystem.monitoringservice.exception.ExceptionConstants;
+import de.muenchen.oss.wahllokalsystem.wls.common.exception.FachlicheWlsException;
+import de.muenchen.oss.wahllokalsystem.wls.common.exception.util.ExceptionFactory;
+import de.muenchen.oss.wahllokalsystem.wls.common.security.domain.BezirkUndWahlID;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+@ExtendWith(MockitoExtension.class)
+class WaehleranzahlValidatorTest {
+
+ @Mock
+ ExceptionFactory exceptionFactory;
+
+ @InjectMocks
+ WaehleranzahlValidator unitUnderTest;
+
+ @Nested
+ class ValidWahlIdUndWahlbezirkIDOrThrow {
+
+ private final FachlicheWlsException mockedFachlicheWlsException = FachlicheWlsException.withCode("").buildWithMessage("");
+
+ @Test
+ void should_throwNoException_when_valid() {
+ Assertions.assertThatNoException().isThrownBy(() -> unitUnderTest.validWahlIdUndWahlbezirkIDOrThrow(new BezirkUndWahlID("wahlID", "wahlbezirkID")));
+ }
+
+ @Test
+ void should_throwException_when_parameterIsNull() {
+ Mockito.when(exceptionFactory.createFachlicheWlsException(ExceptionConstants.GETWAHLBETEILIGUNG_SUCHKRITERIEN_UNVOLLSTAENDIG))
+ .thenReturn(mockedFachlicheWlsException);
+ Assertions.assertThatException().isThrownBy(() -> unitUnderTest.validWahlIdUndWahlbezirkIDOrThrow(null)).isSameAs(mockedFachlicheWlsException);
+ }
+
+ @Test
+ void should_throwException_when_wahlIDIsNull() {
+ Mockito.when(exceptionFactory.createFachlicheWlsException(ExceptionConstants.GETWAHLBETEILIGUNG_SUCHKRITERIEN_UNVOLLSTAENDIG))
+ .thenReturn(mockedFachlicheWlsException);
+ Assertions.assertThatException().isThrownBy(() -> unitUnderTest.validWahlIdUndWahlbezirkIDOrThrow(new BezirkUndWahlID(null, "wahlbezirkID")))
+ .isSameAs(mockedFachlicheWlsException);
+ }
+
+ @Test
+ void should_throwException_when_wahlIDIsEmptyString() {
+ Mockito.when(exceptionFactory.createFachlicheWlsException(ExceptionConstants.GETWAHLBETEILIGUNG_SUCHKRITERIEN_UNVOLLSTAENDIG))
+ .thenReturn(mockedFachlicheWlsException);
+ Assertions.assertThatException().isThrownBy(() -> unitUnderTest.validWahlIdUndWahlbezirkIDOrThrow(new BezirkUndWahlID("", "wahlbezirkID")))
+ .isSameAs(mockedFachlicheWlsException);
+ }
+
+ @Test
+ void should_throwException_when_wahlbezirkIDIsNull() {
+ Mockito.when(exceptionFactory.createFachlicheWlsException(ExceptionConstants.GETWAHLBETEILIGUNG_SUCHKRITERIEN_UNVOLLSTAENDIG))
+ .thenReturn(mockedFachlicheWlsException);
+ Assertions.assertThatException().isThrownBy(() -> unitUnderTest.validWahlIdUndWahlbezirkIDOrThrow(new BezirkUndWahlID("wahlID", null)))
+ .isSameAs(mockedFachlicheWlsException);
+ }
+
+ @Test
+ void should_throwException_when_wahlbezirkIDIsEmptyString() {
+ Mockito.when(exceptionFactory.createFachlicheWlsException(ExceptionConstants.GETWAHLBETEILIGUNG_SUCHKRITERIEN_UNVOLLSTAENDIG))
+ .thenReturn(mockedFachlicheWlsException);
+ Assertions.assertThatException().isThrownBy(() -> unitUnderTest.validWahlIdUndWahlbezirkIDOrThrow(new BezirkUndWahlID("wahlID", "")))
+ .isSameAs(mockedFachlicheWlsException);
+ }
+ }
+
+}
diff --git a/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/utils/Authorities.java b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/utils/Authorities.java
new file mode 100644
index 000000000..fba20d202
--- /dev/null
+++ b/wls-monitoring-service/src/test/java/de/muenchen/oss/wahllokalsystem/monitoringservice/utils/Authorities.java
@@ -0,0 +1,24 @@
+package de.muenchen.oss.wahllokalsystem.monitoringservice.utils;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class Authorities {
+
+ public static final String SERVICE_GET_WAEHLERANZAHL = "Monitoring_BUSINESSACTION_GetWahlbeteiligung";
+ public static final String SERVICE_POST_WAEHLERANZAHL = "Monitoring_BUSINESSACTION_PostWahlbeteiligung";
+
+ public static final String REPOSITORY_READ_WAEHLERANZAHL = "Monitoring_READ_Waehleranzahl";
+ public static final String REPOSITORY_DELETE_WAEHLERANZAHL = "Monitoring_DELETE_Waehleranzahl";
+ public static final String REPOSITORY_WRITE_WAEHLERANZAHL = "Monitoring_WRITE_Waehleranzahl";
+
+ public static final String[] ALL_AUTHORITIES_GET_WAEHLERANZAHL = new String[] {
+ SERVICE_GET_WAEHLERANZAHL,
+ REPOSITORY_READ_WAEHLERANZAHL
+ };
+ public static final String[] ALL_AUTHORITIES_SET_WAEHLERANZAHL = new String[] {
+ SERVICE_POST_WAEHLERANZAHL,
+ REPOSITORY_WRITE_WAEHLERANZAHL
+ };
+}
diff --git a/wls-monitoring-service/src/test/resources/application-test.yml b/wls-monitoring-service/src/test/resources/application-test.yml
new file mode 100644
index 000000000..7b6942275
--- /dev/null
+++ b/wls-monitoring-service/src/test/resources/application-test.yml
@@ -0,0 +1,25 @@
+app:
+ clients:
+ eai:
+ basePath: http://localhost:${wiremock.server.port}/
+
+spring:
+ # Spring JPA
+ h2.console.enabled: true
+ jpa:
+ database: H2
+ hibernate:
+ # always drop and create the db should be the best
+ # configuration for local (development) mode. this
+ # is also the default, that spring offers by convention.
+ # but here explicite:
+ ddl-auto: validate
+ naming.physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
+ # Logging for database operation
+ show-sql: true
+ properties:
+ hibernate:
+ format_sql: true
+wiremock:
+ server:
+ port: 0
diff --git a/wls-monitoring-service/src/test/resources/http.request/http-client.env.json b/wls-monitoring-service/src/test/resources/http.request/http-client.env.json
new file mode 100644
index 000000000..00eae94a3
--- /dev/null
+++ b/wls-monitoring-service/src/test/resources/http.request/http-client.env.json
@@ -0,0 +1,14 @@
+{
+ "docker": {
+ "token_type": "",
+ "auth_token": "",
+ "WLS_MONITORING_SERVICE_URL": "http://localhost:8201",
+ "SSO_URL": "http://kubernetes.docker.internal:8100"
+ },
+ "nonDocker": {
+ "token_type": "",
+ "auth_token": "",
+ "WLS_MONITORING_SERVICE_URL": "http://localhost:39154",
+ "SSO_URL": "http://kubernetes.docker.internal:8100"
+ }
+}
\ No newline at end of file
diff --git a/wls-monitoring-service/src/test/resources/http.request/waehleranzahl.http b/wls-monitoring-service/src/test/resources/http.request/waehleranzahl.http
new file mode 100644
index 000000000..db6c1d12a
--- /dev/null
+++ b/wls-monitoring-service/src/test/resources/http.request/waehleranzahl.http
@@ -0,0 +1,34 @@
+### Get token wls_all
+POST {{ SSO_URL }}/auth/realms/wls_realm/protocol/openid-connect/token
+Content-Type: application/x-www-form-urlencoded
+
+password = test &
+grant_type = password &
+client_secret = top-secret &
+client_id = wls &
+username = wls_all
+
+> {%
+ client.global.set("auth_token", response.body.access_token);
+ client.global.set("token_type", response.body.token_type);
+%}
+
+### get userinfo with auth_token
+GET {{ SSO_URL }}/auth/realms/wls_realm/protocol/openid-connect/userinfo
+Authorization: {{ token_type }} {{ auth_token }}
+
+### get wahleranzahl by wahlID and wahlbezirkID
+GET {{ WLS_MONITORING_SERVICE_URL }}/businessActions/wahlbeteiligung/wahlID01/wahlbezirkID01
+Authorization: {{ token_type }} {{ auth_token }}
+
+### POST waehleranzahl
+POST {{ WLS_MONITORING_SERVICE_URL }}/businessActions/wahlbeteiligung/wahlID01/wahlbezirkID01
+Authorization: {{ token_type }} {{ auth_token }}
+Content-Type: application/json
+
+{
+ "wahlID": "wahlID01",
+ "wahlbezirkID": "wahlbezirk01",
+ "anzahlWaehler": 99,
+ "uhrzeit": "2024-10-21T23:59:12.123"
+}