From 0cdd9fe6d8641706370630415c425dc273c3489a Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Mon, 9 Dec 2024 02:24:25 +0300 Subject: [PATCH 01/40] Include db changelog v3 --- src/main/resources/db/changelog/changelog-master.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/db/changelog/changelog-master.xml b/src/main/resources/db/changelog/changelog-master.xml index fa0bdc8..7d48782 100644 --- a/src/main/resources/db/changelog/changelog-master.xml +++ b/src/main/resources/db/changelog/changelog-master.xml @@ -7,5 +7,6 @@ + \ No newline at end of file From cc2ab2d27194ded3c1f5632b9097bb15c9f6aeb0 Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Mon, 9 Dec 2024 02:27:50 +0300 Subject: [PATCH 02/40] Add sensor_metadata liquibase changelog --- .../resources/db/changelog/changelog-v3.xml | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/main/resources/db/changelog/changelog-v3.xml diff --git a/src/main/resources/db/changelog/changelog-v3.xml b/src/main/resources/db/changelog/changelog-v3.xml new file mode 100644 index 0000000..7979d4c --- /dev/null +++ b/src/main/resources/db/changelog/changelog-v3.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 920ae1ba5d541343db8a4d24085d40e57b0b7e0f Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Mon, 9 Dec 2024 02:33:02 +0300 Subject: [PATCH 03/40] Add sensor entities --- .../cameraonboarding/entity/LightSensor.java | 10 ++++ .../cameraonboarding/entity/MotionSensor.java | 10 ++++ .../cameraonboarding/entity/Sensor.java | 51 +++++++++++++++++++ .../entity/TemperatureSensor.java | 10 ++++ 4 files changed, 81 insertions(+) create mode 100644 src/main/java/com/onboarding/camera/cameraonboarding/entity/LightSensor.java create mode 100644 src/main/java/com/onboarding/camera/cameraonboarding/entity/MotionSensor.java create mode 100644 src/main/java/com/onboarding/camera/cameraonboarding/entity/Sensor.java create mode 100644 src/main/java/com/onboarding/camera/cameraonboarding/entity/TemperatureSensor.java diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/entity/LightSensor.java b/src/main/java/com/onboarding/camera/cameraonboarding/entity/LightSensor.java new file mode 100644 index 0000000..9102eb4 --- /dev/null +++ b/src/main/java/com/onboarding/camera/cameraonboarding/entity/LightSensor.java @@ -0,0 +1,10 @@ +package com.onboarding.camera.cameraonboarding.entity; + +import jakarta.persistence.DiscriminatorValue; +import jakarta.persistence.Entity; + +@Entity +@DiscriminatorValue("LIGHT") +public class LightSensor extends Sensor { + +} diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/entity/MotionSensor.java b/src/main/java/com/onboarding/camera/cameraonboarding/entity/MotionSensor.java new file mode 100644 index 0000000..4a2fca4 --- /dev/null +++ b/src/main/java/com/onboarding/camera/cameraonboarding/entity/MotionSensor.java @@ -0,0 +1,10 @@ +package com.onboarding.camera.cameraonboarding.entity; + +import jakarta.persistence.DiscriminatorValue; +import jakarta.persistence.Entity; + +@Entity +@DiscriminatorValue("MOTION") +public class MotionSensor extends Sensor { + +} diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/entity/Sensor.java b/src/main/java/com/onboarding/camera/cameraonboarding/entity/Sensor.java new file mode 100644 index 0000000..34dfe82 --- /dev/null +++ b/src/main/java/com/onboarding/camera/cameraonboarding/entity/Sensor.java @@ -0,0 +1,51 @@ +package com.onboarding.camera.cameraonboarding.entity; + +import com.onboarding.camera.cameraonboarding.enums.SensorType; +import jakarta.persistence.Column; +import jakarta.persistence.DiscriminatorColumn; +import jakarta.persistence.DiscriminatorType; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.Inheritance; +import jakarta.persistence.InheritanceType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import lombok.Data; +import org.hibernate.annotations.UuidGenerator; + +import java.util.UUID; + +@Data +@Entity +@Table(name = "sensor_metadata") +@Inheritance(strategy = InheritanceType.SINGLE_TABLE) +@DiscriminatorColumn(name = "sensor_type", discriminatorType = DiscriminatorType.STRING) +public abstract class Sensor { + + @Id + @GeneratedValue + @UuidGenerator + @Column(name = "id") + private UUID id; + + @ManyToOne + @JoinColumn(name = "camera_id", nullable = false) + private Camera camera; + + @Column(name = "name", nullable = false) + private String name; + + @Column(name = "version") + private String version; + + @Column(name = "data") + private String data; + + @Column(name = "sensor_type", nullable = false, updatable = false, insertable = false) + @Enumerated(EnumType.STRING) + private SensorType sensorType; +} diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/entity/TemperatureSensor.java b/src/main/java/com/onboarding/camera/cameraonboarding/entity/TemperatureSensor.java new file mode 100644 index 0000000..4195968 --- /dev/null +++ b/src/main/java/com/onboarding/camera/cameraonboarding/entity/TemperatureSensor.java @@ -0,0 +1,10 @@ +package com.onboarding.camera.cameraonboarding.entity; + +import jakarta.persistence.DiscriminatorValue; +import jakarta.persistence.Entity; + +@Entity +@DiscriminatorValue("TEMPERATURE") +public class TemperatureSensor extends Sensor { + +} From e91bb237da7de38b9d323dcc70f2706db75fe4a6 Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Mon, 9 Dec 2024 02:33:41 +0300 Subject: [PATCH 04/40] Add SensorType enum --- .../camera/cameraonboarding/enums/SensorType.java | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/main/java/com/onboarding/camera/cameraonboarding/enums/SensorType.java diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/enums/SensorType.java b/src/main/java/com/onboarding/camera/cameraonboarding/enums/SensorType.java new file mode 100644 index 0000000..fa556b9 --- /dev/null +++ b/src/main/java/com/onboarding/camera/cameraonboarding/enums/SensorType.java @@ -0,0 +1,7 @@ +package com.onboarding.camera.cameraonboarding.enums; + +public enum SensorType { + MOTION, + TEMPERATURE, + LIGHT +} From a4f0f674f49e1988b3b31487eafe636dfb134740 Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Mon, 9 Dec 2024 02:34:23 +0300 Subject: [PATCH 05/40] Add sensor exceptions --- .../exception/SensorMismatchException.java | 7 +++++++ .../exception/SensorNotCreatedException.java | 7 +++++++ .../exception/SensorNotFoundException.java | 7 +++++++ .../exception/SensorNotUpdatedException.java | 7 +++++++ 4 files changed, 28 insertions(+) create mode 100644 src/main/java/com/onboarding/camera/cameraonboarding/exception/SensorMismatchException.java create mode 100644 src/main/java/com/onboarding/camera/cameraonboarding/exception/SensorNotCreatedException.java create mode 100644 src/main/java/com/onboarding/camera/cameraonboarding/exception/SensorNotFoundException.java create mode 100644 src/main/java/com/onboarding/camera/cameraonboarding/exception/SensorNotUpdatedException.java diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/exception/SensorMismatchException.java b/src/main/java/com/onboarding/camera/cameraonboarding/exception/SensorMismatchException.java new file mode 100644 index 0000000..6985419 --- /dev/null +++ b/src/main/java/com/onboarding/camera/cameraonboarding/exception/SensorMismatchException.java @@ -0,0 +1,7 @@ +package com.onboarding.camera.cameraonboarding.exception; + +public class SensorMismatchException extends RuntimeException { + public SensorMismatchException(String message) { + super(message); + } +} diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/exception/SensorNotCreatedException.java b/src/main/java/com/onboarding/camera/cameraonboarding/exception/SensorNotCreatedException.java new file mode 100644 index 0000000..64e626f --- /dev/null +++ b/src/main/java/com/onboarding/camera/cameraonboarding/exception/SensorNotCreatedException.java @@ -0,0 +1,7 @@ +package com.onboarding.camera.cameraonboarding.exception; + +public class SensorNotCreatedException extends RuntimeException { + public SensorNotCreatedException(String message) { + super(message); + } +} diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/exception/SensorNotFoundException.java b/src/main/java/com/onboarding/camera/cameraonboarding/exception/SensorNotFoundException.java new file mode 100644 index 0000000..4e42903 --- /dev/null +++ b/src/main/java/com/onboarding/camera/cameraonboarding/exception/SensorNotFoundException.java @@ -0,0 +1,7 @@ +package com.onboarding.camera.cameraonboarding.exception; + +public class SensorNotFoundException extends RuntimeException { + public SensorNotFoundException(String message) { + super(message); + } +} diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/exception/SensorNotUpdatedException.java b/src/main/java/com/onboarding/camera/cameraonboarding/exception/SensorNotUpdatedException.java new file mode 100644 index 0000000..92231a6 --- /dev/null +++ b/src/main/java/com/onboarding/camera/cameraonboarding/exception/SensorNotUpdatedException.java @@ -0,0 +1,7 @@ +package com.onboarding.camera.cameraonboarding.exception; + +public class SensorNotUpdatedException extends RuntimeException { + public SensorNotUpdatedException(String message) { + super(message); + } +} From 25acda8b91f6b8077020691c4b8c53b98d4c5b31 Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Mon, 9 Dec 2024 02:35:56 +0300 Subject: [PATCH 06/40] Add sensor repositories --- .../repository/LightSensorRepository.java | 16 ++++++++++++++++ .../repository/MotionSensorRepository.java | 16 ++++++++++++++++ .../repository/TemperatureSensorRepository.java | 16 ++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 src/main/java/com/onboarding/camera/cameraonboarding/repository/LightSensorRepository.java create mode 100644 src/main/java/com/onboarding/camera/cameraonboarding/repository/MotionSensorRepository.java create mode 100644 src/main/java/com/onboarding/camera/cameraonboarding/repository/TemperatureSensorRepository.java diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/repository/LightSensorRepository.java b/src/main/java/com/onboarding/camera/cameraonboarding/repository/LightSensorRepository.java new file mode 100644 index 0000000..d6a90e8 --- /dev/null +++ b/src/main/java/com/onboarding/camera/cameraonboarding/repository/LightSensorRepository.java @@ -0,0 +1,16 @@ +package com.onboarding.camera.cameraonboarding.repository; + +import com.onboarding.camera.cameraonboarding.entity.LightSensor; +import com.onboarding.camera.cameraonboarding.enums.SensorType; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; +import java.util.UUID; + +public interface LightSensorRepository extends JpaRepository { + + @Query("SELECT s FROM LightSensor s WHERE s.camera.camId = :cameraId AND s.sensorType = :sensorType") + List findByCameraIdAndSensorType(@Param("cameraId") UUID cameraId, @Param("sensorType") SensorType sensorType); +} diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/repository/MotionSensorRepository.java b/src/main/java/com/onboarding/camera/cameraonboarding/repository/MotionSensorRepository.java new file mode 100644 index 0000000..64b3cf4 --- /dev/null +++ b/src/main/java/com/onboarding/camera/cameraonboarding/repository/MotionSensorRepository.java @@ -0,0 +1,16 @@ +package com.onboarding.camera.cameraonboarding.repository; + +import com.onboarding.camera.cameraonboarding.entity.MotionSensor; +import com.onboarding.camera.cameraonboarding.enums.SensorType; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; +import java.util.UUID; + +public interface MotionSensorRepository extends JpaRepository { + + @Query("SELECT s FROM MotionSensor s WHERE s.camera.camId = :cameraId AND s.sensorType = :sensorType") + List findByCameraIdAndSensorType(@Param("cameraId") UUID cameraId, @Param("sensorType") SensorType sensorType); +} diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/repository/TemperatureSensorRepository.java b/src/main/java/com/onboarding/camera/cameraonboarding/repository/TemperatureSensorRepository.java new file mode 100644 index 0000000..98f8311 --- /dev/null +++ b/src/main/java/com/onboarding/camera/cameraonboarding/repository/TemperatureSensorRepository.java @@ -0,0 +1,16 @@ +package com.onboarding.camera.cameraonboarding.repository; + +import com.onboarding.camera.cameraonboarding.entity.TemperatureSensor; +import com.onboarding.camera.cameraonboarding.enums.SensorType; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; +import java.util.UUID; + +public interface TemperatureSensorRepository extends JpaRepository { + + @Query("SELECT s FROM TemperatureSensor s WHERE s.camera.camId = :cameraId AND s.sensorType = :sensorType") + List findByCameraIdAndSensorType(@Param("cameraId") UUID cameraId, @Param("sensorType") SensorType sensorType); +} From 80e105d2793ec100aa25e71c9bb25a6345384cc9 Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Mon, 9 Dec 2024 02:37:27 +0300 Subject: [PATCH 07/40] Add sensor service --- .../service/SensorService.java | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/main/java/com/onboarding/camera/cameraonboarding/service/SensorService.java diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/service/SensorService.java b/src/main/java/com/onboarding/camera/cameraonboarding/service/SensorService.java new file mode 100644 index 0000000..dac83ca --- /dev/null +++ b/src/main/java/com/onboarding/camera/cameraonboarding/service/SensorService.java @@ -0,0 +1,59 @@ +package com.onboarding.camera.cameraonboarding.service; + +import com.onboarding.camera.cameraonboarding.entity.Sensor; +import com.onboarding.camera.cameraonboarding.exception.SensorNotCreatedException; +import com.onboarding.camera.cameraonboarding.exception.SensorNotFoundException; +import com.onboarding.camera.cameraonboarding.exception.SensorNotUpdatedException; + +import java.util.List; +import java.util.UUID; + +public interface SensorService { + + /** + * this method is used for create sensor to specified camera + * + * @param cameraId camera id + * @param sensor sensor + * @return Sensor created sensor + * @throws IllegalArgumentException if sensor type does not match + * @throws SensorNotCreatedException if unexpected error occurs while creating sensor + */ + T handleCreateSensor(UUID cameraId, T sensor); + + /** + * this method is used for get all sensors with related camera by camera ID + * + * @param cameraId camera id + * @return List sensors with specified camera + * @throws SensorNotFoundException if sensors not found + */ + List handleGetSensorsByCameraId(UUID cameraId); + + /** + * this method is used for update sensor by sensor ID + * + * @param sensorId sensor id + * @param sensor sensor + * @return Sensor updated sensor + * @throws SensorNotUpdatedException if unexpected error occurs while updating sensor + */ + T handleUpdateSensor(UUID sensorId, T sensor); + + /** + * this method is used for get sensor by sensor ID + * + * @param sensorId sensor id + * @return Sensor retrieved sensor + * @throws SensorNotFoundException if sensor not found + */ + T getSensorById(UUID sensorId); + + /** + * this method is used for deleting sensor by sensor ID + * + * @param sensorId sensor id + * @throws SensorNotUpdatedException if unexpected error occurs while deleting sensor + */ + void handleDeleteSensor(UUID sensorId); +} From 167dd8b14e4edbfd91e50a46ec77514dd8fe6c71 Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Mon, 9 Dec 2024 02:37:54 +0300 Subject: [PATCH 08/40] Add sensor service implementations --- .../service/impl/LightSensorService.java | 91 +++++++++++++++++++ .../service/impl/MotionSensorService.java | 90 ++++++++++++++++++ .../impl/TemperatureSensorService.java | 90 ++++++++++++++++++ 3 files changed, 271 insertions(+) create mode 100644 src/main/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorService.java create mode 100644 src/main/java/com/onboarding/camera/cameraonboarding/service/impl/MotionSensorService.java create mode 100644 src/main/java/com/onboarding/camera/cameraonboarding/service/impl/TemperatureSensorService.java diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorService.java b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorService.java new file mode 100644 index 0000000..1838799 --- /dev/null +++ b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorService.java @@ -0,0 +1,91 @@ +package com.onboarding.camera.cameraonboarding.service.impl; + +import com.onboarding.camera.cameraonboarding.entity.LightSensor; +import com.onboarding.camera.cameraonboarding.enums.SensorType; +import com.onboarding.camera.cameraonboarding.exception.SensorNotCreatedException; +import com.onboarding.camera.cameraonboarding.exception.SensorNotFoundException; +import com.onboarding.camera.cameraonboarding.exception.SensorNotUpdatedException; +import com.onboarding.camera.cameraonboarding.repository.LightSensorRepository; +import com.onboarding.camera.cameraonboarding.service.CameraService; +import com.onboarding.camera.cameraonboarding.service.SensorService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.UUID; + +@Slf4j +@RequiredArgsConstructor +@Service +public class LightSensorService implements SensorService { + + private final LightSensorRepository lightSensorRepository; + + private final CameraService cameraService; + + @Override + @Transactional + public LightSensor handleCreateSensor(UUID cameraId, LightSensor sensor) { + try { + sensor.setCamera(cameraService.getCameraById(cameraId)); + sensor.setSensorType(SensorType.LIGHT); + LightSensor savedSensor = lightSensorRepository.save(sensor); + log.info("Creating sensor: {}", sensor); + return savedSensor; + } catch (SensorNotCreatedException ex) { + log.error("Failed to create sensor, camera:{}:ex:{}", cameraId, ex.getMessage()); + throw new SensorNotCreatedException(String.format("Failed to create sensor: %s", ex.getMessage())); + } + } + + @Override + public List handleGetSensorsByCameraId(UUID cameraId) { + try { + log.info("Getting sensors by camera id: {}", cameraId); + return lightSensorRepository.findByCameraIdAndSensorType(cameraId, SensorType.LIGHT); + } catch (SensorNotFoundException ex) { + log.error("Exception occurred while getting sensors, cameraId:{}", cameraId); + throw new SensorNotFoundException(String.format("Error occurred while getting sensors: %s", ex.getMessage())); + } + } + + @Override + @Transactional + public LightSensor handleUpdateSensor(UUID sensorId, LightSensor sensor) { + try { + LightSensor existingSensor = getSensorById(sensorId); + existingSensor.setName(sensor.getName()); + existingSensor.setVersion(sensor.getVersion()); + existingSensor.setData(sensor.getData()); + log.info("Updating sensor: {}", existingSensor); + return lightSensorRepository.save(existingSensor); + } catch (SensorNotUpdatedException ex) { + log.error("Exception occurred while updating sensor, sensorId:{}", sensorId); + throw new SensorNotUpdatedException(String.format("Error occurred while updating sensors: %s", ex.getMessage())); + } + } + + @Override + public LightSensor getSensorById(UUID sensorId) { + if (sensorId == null) { + throw new IllegalArgumentException("Sensor ID cannot be null"); + } + + return lightSensorRepository.findById(sensorId) + .orElseThrow(() -> new SensorNotFoundException(String.format("Sensor not found with id: %s", sensorId))); + } + + @Override + public void handleDeleteSensor(UUID sensorId) { + try { + LightSensor deletedSensor = getSensorById(sensorId); + log.info("Deleting sensor: {}", deletedSensor); + lightSensorRepository.deleteById(sensorId); + } catch (SensorNotUpdatedException ex) { + log.error("Exception occurred while deleting sensor, sensorId:{}", sensorId); + throw new SensorNotUpdatedException(String.format("Error occurred while deleting sensor: %s", ex.getMessage())); + } + } +} diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/MotionSensorService.java b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/MotionSensorService.java new file mode 100644 index 0000000..5171103 --- /dev/null +++ b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/MotionSensorService.java @@ -0,0 +1,90 @@ +package com.onboarding.camera.cameraonboarding.service.impl; + +import com.onboarding.camera.cameraonboarding.entity.MotionSensor; +import com.onboarding.camera.cameraonboarding.enums.SensorType; +import com.onboarding.camera.cameraonboarding.exception.SensorNotCreatedException; +import com.onboarding.camera.cameraonboarding.exception.SensorNotFoundException; +import com.onboarding.camera.cameraonboarding.exception.SensorNotUpdatedException; +import com.onboarding.camera.cameraonboarding.repository.MotionSensorRepository; +import com.onboarding.camera.cameraonboarding.service.CameraService; +import com.onboarding.camera.cameraonboarding.service.SensorService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.UUID; + +@Slf4j +@RequiredArgsConstructor +@Service +public class MotionSensorService implements SensorService { + + private final MotionSensorRepository motionSensorRepository; + + private final CameraService cameraService; + + @Override + @Transactional + public MotionSensor handleCreateSensor(UUID cameraId, MotionSensor sensor) { + try { + sensor.setCamera(cameraService.getCameraById(cameraId)); + sensor.setSensorType(SensorType.MOTION); + log.info("Creating sensor: {}", sensor); + return motionSensorRepository.save(sensor); + } catch (SensorNotCreatedException ex) { + log.error("Failed to create sensor, camera:{}:ex:{}", cameraId, ex.getMessage()); + throw new SensorNotCreatedException(String.format("Failed to create sensor: %s", ex.getMessage())); + } + } + + @Override + public List handleGetSensorsByCameraId(UUID cameraId) { + try { + log.info("Getting sensors by camera id: {}", cameraId); + return motionSensorRepository.findByCameraIdAndSensorType(cameraId, SensorType.MOTION); + } catch (SensorNotFoundException ex) { + log.error("Exception occurred while getting sensors, cameraId:{}", cameraId); + throw new SensorNotFoundException(String.format("Error occurred while getting sensors: %s", ex.getMessage())); + } + } + + @Override + @Transactional + public MotionSensor handleUpdateSensor(UUID sensorId, MotionSensor sensor) { + try { + MotionSensor existingSensor = getSensorById(sensorId); + existingSensor.setName(sensor.getName()); + existingSensor.setVersion(sensor.getVersion()); + existingSensor.setData(sensor.getData()); + log.info("Updating sensor: {}", existingSensor); + return motionSensorRepository.save(existingSensor); + } catch (SensorNotUpdatedException ex) { + log.error("Exception occurred while updating sensor, sensorId:{}", sensorId); + throw new SensorNotUpdatedException(String.format("Error occurred while updating sensors: %s", ex.getMessage())); + } + } + + @Override + public MotionSensor getSensorById(UUID sensorId) { + if (sensorId == null) { + throw new IllegalArgumentException("Sensor ID cannot be null"); + } + + return motionSensorRepository.findById(sensorId) + .orElseThrow(() -> new SensorNotFoundException(String.format("Sensor not found with id: %s", sensorId))); + } + + @Override + public void handleDeleteSensor(UUID sensorId) { + try { + MotionSensor deletedSensor = getSensorById(sensorId); + log.info("Deleting sensor: {}", deletedSensor); + motionSensorRepository.deleteById(sensorId); + } catch (SensorNotUpdatedException ex) { + log.error("Exception occurred while deleting sensor, sensorId:{}", sensorId); + throw new SensorNotUpdatedException(String.format("Error occurred while deleting sensor: %s", ex.getMessage())); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/TemperatureSensorService.java b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/TemperatureSensorService.java new file mode 100644 index 0000000..fc3b746 --- /dev/null +++ b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/TemperatureSensorService.java @@ -0,0 +1,90 @@ +package com.onboarding.camera.cameraonboarding.service.impl; + +import com.onboarding.camera.cameraonboarding.entity.TemperatureSensor; +import com.onboarding.camera.cameraonboarding.enums.SensorType; +import com.onboarding.camera.cameraonboarding.exception.SensorNotCreatedException; +import com.onboarding.camera.cameraonboarding.exception.SensorNotFoundException; +import com.onboarding.camera.cameraonboarding.exception.SensorNotUpdatedException; +import com.onboarding.camera.cameraonboarding.repository.TemperatureSensorRepository; +import com.onboarding.camera.cameraonboarding.service.CameraService; +import com.onboarding.camera.cameraonboarding.service.SensorService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.UUID; + +@Slf4j +@RequiredArgsConstructor +@Service +public class TemperatureSensorService implements SensorService { + + private final TemperatureSensorRepository temperatureSensorRepository; + + private final CameraService cameraService; + + @Override + @Transactional + public TemperatureSensor handleCreateSensor(UUID cameraId, TemperatureSensor sensor) { + try { + sensor.setCamera(cameraService.getCameraById(cameraId)); + sensor.setSensorType(SensorType.TEMPERATURE); + log.info("Creating sensor: {}", sensor); + return temperatureSensorRepository.save(sensor); + } catch (SensorNotCreatedException ex) { + log.error("Failed to create sensor, camera:{}:ex:{}", cameraId, ex.getMessage()); + throw new SensorNotCreatedException(String.format("Failed to create sensor: %s", ex.getMessage())); + } + } + + @Override + public List handleGetSensorsByCameraId(UUID cameraId) { + try { + log.info("Getting sensors by camera id: {}", cameraId); + return temperatureSensorRepository.findByCameraIdAndSensorType(cameraId, SensorType.TEMPERATURE); + } catch (SensorNotFoundException ex) { + log.error("Exception occurred while getting sensors, cameraId:{}", cameraId); + throw new SensorNotFoundException(String.format("Error occurred while getting sensors: %s", ex.getMessage())); + } + } + + @Override + @Transactional + public TemperatureSensor handleUpdateSensor(UUID sensorId, TemperatureSensor sensor) { + try { + TemperatureSensor existingSensor = getSensorById(sensorId); + existingSensor.setName(sensor.getName()); + existingSensor.setVersion(sensor.getVersion()); + existingSensor.setData(sensor.getData()); + log.info("Updating sensor: {}", existingSensor); + return temperatureSensorRepository.save(existingSensor); + } catch (SensorNotUpdatedException ex) { + log.error("Exception occurred while updating sensor, sensorId:{}", sensorId); + throw new SensorNotUpdatedException(String.format("Error occurred while updating sensors: %s", ex.getMessage())); + } + } + + @Override + public TemperatureSensor getSensorById(UUID sensorId) { + if (sensorId == null) { + throw new IllegalArgumentException("Sensor ID cannot be null"); + } + + return temperatureSensorRepository.findById(sensorId) + .orElseThrow(() -> new SensorNotFoundException(String.format("Sensor not found with id: %s", sensorId))); + } + + @Override + public void handleDeleteSensor(UUID sensorId) { + try { + TemperatureSensor deletedSensor = getSensorById(sensorId); + log.info("Deleting sensor: {}", deletedSensor); + temperatureSensorRepository.deleteById(sensorId); + } catch (SensorNotUpdatedException ex) { + log.error("Exception occurred while deleting sensor, sensorId:{}", sensorId); + throw new SensorNotUpdatedException(String.format("Error occurred while deleting sensor: %s", ex.getMessage())); + } + } +} From 8e23d307fd0e91c6bf72995938ea9fd0391295bd Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Mon, 9 Dec 2024 02:38:47 +0300 Subject: [PATCH 09/40] Add sensor dto --- .../cameraonboarding/dto/SensorDto.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/main/java/com/onboarding/camera/cameraonboarding/dto/SensorDto.java diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/dto/SensorDto.java b/src/main/java/com/onboarding/camera/cameraonboarding/dto/SensorDto.java new file mode 100644 index 0000000..4891045 --- /dev/null +++ b/src/main/java/com/onboarding/camera/cameraonboarding/dto/SensorDto.java @@ -0,0 +1,28 @@ +package com.onboarding.camera.cameraonboarding.dto; + +import com.onboarding.camera.cameraonboarding.enums.SensorType; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SensorDto { + + @NotBlank(message = "Sensor name cannot be blank") + @Size(min = 2, max = 100, message = "Sensor name should be between 2 and 100 characters") + private String name; + + @NotBlank(message = "Version cannot be blank") + @Size(min = 2, max = 50, message = "Version should be between 2 and 50 characters") + private String version; + + @NotNull(message = "Sensor type cannot be null") + private SensorType sensorType; + + private String data; +} From 2ee497aa287559e275e9b44824bb231daa75da92 Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Mon, 9 Dec 2024 02:39:11 +0300 Subject: [PATCH 10/40] Add sensor response --- .../cameraonboarding/dto/SensorResponse.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/main/java/com/onboarding/camera/cameraonboarding/dto/SensorResponse.java diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/dto/SensorResponse.java b/src/main/java/com/onboarding/camera/cameraonboarding/dto/SensorResponse.java new file mode 100644 index 0000000..51cdb55 --- /dev/null +++ b/src/main/java/com/onboarding/camera/cameraonboarding/dto/SensorResponse.java @@ -0,0 +1,15 @@ +package com.onboarding.camera.cameraonboarding.dto; + +import com.onboarding.camera.cameraonboarding.enums.SensorType; +import lombok.Data; + +import java.util.UUID; + +@Data +public class SensorResponse { + private UUID id; + private String name; + private String version; + private SensorType sensorType; + private String data; +} From 9f3e26b654fafc51e46af7c31f619f3126847c6d Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Mon, 9 Dec 2024 02:39:41 +0300 Subject: [PATCH 11/40] Add sensor dto converter --- .../converter/SensorDtoConverter.java | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/main/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverter.java diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverter.java b/src/main/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverter.java new file mode 100644 index 0000000..690eeb6 --- /dev/null +++ b/src/main/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverter.java @@ -0,0 +1,72 @@ +package com.onboarding.camera.cameraonboarding.converter; + +import com.onboarding.camera.cameraonboarding.dto.SensorDto; +import com.onboarding.camera.cameraonboarding.dto.SensorResponse; +import com.onboarding.camera.cameraonboarding.entity.LightSensor; +import com.onboarding.camera.cameraonboarding.entity.MotionSensor; +import com.onboarding.camera.cameraonboarding.entity.Sensor; +import com.onboarding.camera.cameraonboarding.entity.TemperatureSensor; +import com.onboarding.camera.cameraonboarding.enums.SensorType; +import com.onboarding.camera.cameraonboarding.exception.SensorMismatchException; +import org.springframework.stereotype.Component; + +import java.util.stream.Stream; + +@Component +public class SensorDtoConverter { + + public MotionSensor toMotionEntity(SensorDto sensorDto) { + return Stream.of(sensorDto) + .filter(dto -> dto.getSensorType() == SensorType.MOTION) + .map(dto -> { + MotionSensor sensorMetadata = new MotionSensor(); + sensorMetadata.setName(dto.getName()); + sensorMetadata.setVersion(dto.getVersion()); + sensorMetadata.setSensorType(dto.getSensorType()); + sensorMetadata.setData(dto.getData()); + return sensorMetadata; + }) + .findFirst() + .orElseThrow(() -> new SensorMismatchException("Invalid sensor type for MotionSensor")); + } + + public LightSensor toLightEntity(SensorDto sensorDto) { + return Stream.of(sensorDto) + .filter(dto -> dto.getSensorType() == SensorType.LIGHT) + .map(dto -> { + LightSensor sensorMetadata = new LightSensor(); + sensorMetadata.setName(dto.getName()); + sensorMetadata.setVersion(dto.getVersion()); + sensorMetadata.setSensorType(dto.getSensorType()); + sensorMetadata.setData(dto.getData()); + return sensorMetadata; + }) + .findFirst() + .orElseThrow(() -> new SensorMismatchException("Invalid sensor type for LightSensor")); + } + + public TemperatureSensor toTemperatureEntity(SensorDto sensorDto) { + return Stream.of(sensorDto) + .filter(dto -> dto.getSensorType() == SensorType.TEMPERATURE) + .map(dto -> { + TemperatureSensor sensorMetadata = new TemperatureSensor(); + sensorMetadata.setName(dto.getName()); + sensorMetadata.setVersion(dto.getVersion()); + sensorMetadata.setSensorType(dto.getSensorType()); + sensorMetadata.setData(dto.getData()); + return sensorMetadata; + }) + .findFirst() + .orElseThrow(() -> new SensorMismatchException("Invalid sensor type for TemperatureSensor")); + } + + public SensorResponse toSensorResponse(Sensor sensor) { + SensorResponse response = new SensorResponse(); + response.setId(sensor.getId()); + response.setName(sensor.getName()); + response.setVersion(sensor.getVersion()); + response.setSensorType(sensor.getSensorType()); + response.setData(sensor.getData()); + return response; + } +} From ecc1cda5e87b138d3ba8700972b6a429fade5b2d Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Mon, 9 Dec 2024 02:41:04 +0300 Subject: [PATCH 12/40] Add sensor exception handler methods --- .../controller/GlobalExceptionHandler.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/controller/GlobalExceptionHandler.java b/src/main/java/com/onboarding/camera/cameraonboarding/controller/GlobalExceptionHandler.java index 30bd025..95714c6 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/controller/GlobalExceptionHandler.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/controller/GlobalExceptionHandler.java @@ -10,6 +10,10 @@ import com.onboarding.camera.cameraonboarding.exception.ImageNotFoundException; import com.onboarding.camera.cameraonboarding.exception.ImageNotUploadedException; import com.onboarding.camera.cameraonboarding.exception.LocationNotAddedException; +import com.onboarding.camera.cameraonboarding.exception.SensorMismatchException; +import com.onboarding.camera.cameraonboarding.exception.SensorNotCreatedException; +import com.onboarding.camera.cameraonboarding.exception.SensorNotFoundException; +import com.onboarding.camera.cameraonboarding.exception.SensorNotUpdatedException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.MethodArgumentNotValidException; @@ -166,5 +170,53 @@ public ResponseEntity handleLocationNotAddedException(LocationNot return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR); } + + @ExceptionHandler(SensorNotCreatedException.class) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + @ResponseBody + public ResponseEntity handleSensorNotCreatedException(SensorNotCreatedException ex) { + ErrorResponse errorResponse = new ErrorResponse(); + + errorResponse.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR.value()); + errorResponse.setMessage(ex.getMessage()); + + return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR); + } + + @ExceptionHandler(SensorNotFoundException.class) + @ResponseStatus(HttpStatus.NOT_FOUND) + @ResponseBody + public ResponseEntity handleSensorNotFoundException(SensorNotFoundException ex) { + ErrorResponse errorResponse = new ErrorResponse(); + + errorResponse.setStatusCode(HttpStatus.NOT_FOUND.value()); + errorResponse.setMessage(ex.getMessage()); + + return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(SensorNotUpdatedException.class) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + @ResponseBody + public ResponseEntity handleSensorNotUpdatedException(SensorNotUpdatedException ex) { + ErrorResponse errorResponse = new ErrorResponse(); + + errorResponse.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR.value()); + errorResponse.setMessage(ex.getMessage()); + + return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR); + } + + @ExceptionHandler(SensorMismatchException.class) + @ResponseStatus(HttpStatus.CONFLICT) + @ResponseBody + public ResponseEntity handleSensorMismatchException(SensorMismatchException ex) { + ErrorResponse errorResponse = new ErrorResponse(); + + errorResponse.setStatusCode(HttpStatus.CONFLICT.value()); + errorResponse.setMessage(ex.getMessage()); + + return new ResponseEntity<>(errorResponse, HttpStatus.CONFLICT); + } } From 3ae6b1a3157dd6dc25e5d5a22727d4e206c0fc28 Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Mon, 9 Dec 2024 02:41:57 +0300 Subject: [PATCH 13/40] Add sensor REST controllers --- .../controller/LightSensorController.java | 73 +++++++++++++++++++ .../controller/MotionSensorController.java | 73 +++++++++++++++++++ .../TemperatureSensorController.java | 72 ++++++++++++++++++ 3 files changed, 218 insertions(+) create mode 100644 src/main/java/com/onboarding/camera/cameraonboarding/controller/LightSensorController.java create mode 100644 src/main/java/com/onboarding/camera/cameraonboarding/controller/MotionSensorController.java create mode 100644 src/main/java/com/onboarding/camera/cameraonboarding/controller/TemperatureSensorController.java diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/controller/LightSensorController.java b/src/main/java/com/onboarding/camera/cameraonboarding/controller/LightSensorController.java new file mode 100644 index 0000000..30eb81c --- /dev/null +++ b/src/main/java/com/onboarding/camera/cameraonboarding/controller/LightSensorController.java @@ -0,0 +1,73 @@ +package com.onboarding.camera.cameraonboarding.controller; + +import com.onboarding.camera.cameraonboarding.converter.SensorDtoConverter; +import com.onboarding.camera.cameraonboarding.dto.SensorDto; +import com.onboarding.camera.cameraonboarding.dto.SensorResponse; +import com.onboarding.camera.cameraonboarding.entity.LightSensor; +import com.onboarding.camera.cameraonboarding.service.impl.LightSensorService; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +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.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.UUID; + +@RestController +@RequestMapping("${api.version}/camera/{cameraId}/sensor/light") +@RequiredArgsConstructor +public class LightSensorController { + + private final LightSensorService lightSensorService; + + private final SensorDtoConverter sensorDtoConverter; + + @PostMapping + public ResponseEntity addLightSensor( + @PathVariable UUID cameraId, + @Valid @RequestBody SensorDto sensorDto) { + + LightSensor sensorMetadata = sensorDtoConverter.toLightEntity(sensorDto); + LightSensor savedSensor = lightSensorService.handleCreateSensor(cameraId, sensorMetadata); + SensorResponse sensorResponse = sensorDtoConverter.toSensorResponse(savedSensor); + + return new ResponseEntity<>(sensorResponse, HttpStatus.CREATED); + } + + @GetMapping + public ResponseEntity> getLightSensors( + @PathVariable UUID cameraId) { + + List sensors = lightSensorService.handleGetSensorsByCameraId(cameraId); + return ResponseEntity.ok(sensors); + } + + @PutMapping("/{sensorId}") + public ResponseEntity updateLightSensor( + @PathVariable UUID cameraId, + @PathVariable UUID sensorId, + @Valid @RequestBody SensorDto sensorDto) { + + LightSensor sensorMetadata = sensorDtoConverter.toLightEntity(sensorDto); + LightSensor updatedSensor = lightSensorService.handleUpdateSensor(sensorId, sensorMetadata); + SensorResponse sensorResponse = sensorDtoConverter.toSensorResponse(updatedSensor); + return ResponseEntity.ok(sensorResponse); + } + + @DeleteMapping("/{sensorId}") + public ResponseEntity deleteLightSensor( + @PathVariable UUID cameraId, + @PathVariable UUID sensorId) { + + lightSensorService.handleDeleteSensor(sensorId); + return ResponseEntity.noContent().build(); + } +} diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/controller/MotionSensorController.java b/src/main/java/com/onboarding/camera/cameraonboarding/controller/MotionSensorController.java new file mode 100644 index 0000000..3a1f7fb --- /dev/null +++ b/src/main/java/com/onboarding/camera/cameraonboarding/controller/MotionSensorController.java @@ -0,0 +1,73 @@ +package com.onboarding.camera.cameraonboarding.controller; + +import com.onboarding.camera.cameraonboarding.converter.SensorDtoConverter; +import com.onboarding.camera.cameraonboarding.dto.SensorDto; +import com.onboarding.camera.cameraonboarding.dto.SensorResponse; +import com.onboarding.camera.cameraonboarding.entity.MotionSensor; +import com.onboarding.camera.cameraonboarding.service.impl.MotionSensorService; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +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.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.UUID; + +@RestController +@RequestMapping("${api.version}/camera/{cameraId}/sensor/motion") +@RequiredArgsConstructor +public class MotionSensorController { + + private final MotionSensorService motionSensorService; + + private final SensorDtoConverter sensorDtoConverter; + + @PostMapping + public ResponseEntity addMotionSensor( + @PathVariable UUID cameraId, + @Valid @RequestBody SensorDto sensorDto) { + + MotionSensor motionSensor = sensorDtoConverter.toMotionEntity(sensorDto); + MotionSensor savedSensor = motionSensorService.handleCreateSensor(cameraId, motionSensor); + SensorResponse sensorResponse = sensorDtoConverter.toSensorResponse(savedSensor); + + return new ResponseEntity<>(sensorResponse, HttpStatus.CREATED); + } + + @GetMapping + public ResponseEntity> getMotionSensors( + @PathVariable UUID cameraId) { + + List sensors = motionSensorService.handleGetSensorsByCameraId(cameraId); + return ResponseEntity.ok(sensors); + } + + @PutMapping("/{sensorId}") + public ResponseEntity updateMotionSensor( + @PathVariable UUID cameraId, + @PathVariable UUID sensorId, + @Valid @RequestBody SensorDto sensorDto) { + + MotionSensor motionSensor = sensorDtoConverter.toMotionEntity(sensorDto); + MotionSensor updatedSensor = motionSensorService.handleUpdateSensor(sensorId, motionSensor); + SensorResponse sensorResponse = sensorDtoConverter.toSensorResponse(updatedSensor); + return ResponseEntity.ok(sensorResponse); + } + + @DeleteMapping("/{sensorId}") + public ResponseEntity deleteMotionSensor( + @PathVariable UUID cameraId, + @PathVariable UUID sensorId) { + + motionSensorService.handleDeleteSensor(sensorId); + return ResponseEntity.noContent().build(); + } +} diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/controller/TemperatureSensorController.java b/src/main/java/com/onboarding/camera/cameraonboarding/controller/TemperatureSensorController.java new file mode 100644 index 0000000..d1e5a30 --- /dev/null +++ b/src/main/java/com/onboarding/camera/cameraonboarding/controller/TemperatureSensorController.java @@ -0,0 +1,72 @@ +package com.onboarding.camera.cameraonboarding.controller; + +import com.onboarding.camera.cameraonboarding.converter.SensorDtoConverter; +import com.onboarding.camera.cameraonboarding.dto.SensorDto; +import com.onboarding.camera.cameraonboarding.dto.SensorResponse; +import com.onboarding.camera.cameraonboarding.entity.TemperatureSensor; +import com.onboarding.camera.cameraonboarding.service.impl.TemperatureSensorService; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +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.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.UUID; + +@RestController +@RequestMapping("${api.version}/camera/{cameraId}/sensor/temperature") +@RequiredArgsConstructor +public class TemperatureSensorController { + + private final TemperatureSensorService temperatureSensorService; + + private final SensorDtoConverter sensorDtoConverter; + + @PostMapping + public ResponseEntity addTemperatureSensor( + @PathVariable UUID cameraId, + @Valid @RequestBody SensorDto sensorDto) { + + TemperatureSensor sensorMetadata = sensorDtoConverter.toTemperatureEntity(sensorDto); + TemperatureSensor savedSensor = temperatureSensorService.handleCreateSensor(cameraId, sensorMetadata); + SensorResponse sensorResponse = sensorDtoConverter.toSensorResponse(savedSensor); + return new ResponseEntity<>(sensorResponse, HttpStatus.CREATED); + } + + @GetMapping + public ResponseEntity> getTemperatureSensors( + @PathVariable UUID cameraId) { + + List sensors = temperatureSensorService.handleGetSensorsByCameraId(cameraId); + return ResponseEntity.ok(sensors); + } + + @PutMapping("/{sensorId}") + public ResponseEntity updateTemperatureSensor( + @PathVariable UUID cameraId, + @PathVariable UUID sensorId, + @Valid @RequestBody SensorDto sensorDto) { + + TemperatureSensor sensorMetadata = sensorDtoConverter.toTemperatureEntity(sensorDto); + TemperatureSensor updatedSensor = temperatureSensorService.handleUpdateSensor(sensorId, sensorMetadata); + SensorResponse sensorResponse = sensorDtoConverter.toSensorResponse(updatedSensor); + return ResponseEntity.ok(sensorResponse); + } + + @DeleteMapping("/{sensorId}") + public ResponseEntity deleteTemperatureSensor( + @PathVariable UUID cameraId, + @PathVariable UUID sensorId) { + + temperatureSensorService.handleDeleteSensor(sensorId); + return ResponseEntity.noContent().build(); + } +} From ae5d91b74574bfabbc323c42bc6ee5286b02969f Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Sat, 14 Dec 2024 14:46:13 +0300 Subject: [PATCH 14/40] Include changelog v3 --- src/main/resources/db/changelog/changelog-master.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/db/changelog/changelog-master.xml b/src/main/resources/db/changelog/changelog-master.xml index fa0bdc8..7d48782 100644 --- a/src/main/resources/db/changelog/changelog-master.xml +++ b/src/main/resources/db/changelog/changelog-master.xml @@ -7,5 +7,6 @@ + \ No newline at end of file From 0b2c00d70ad5a272b2b635ef7fae309190372337 Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Sat, 14 Dec 2024 14:47:15 +0300 Subject: [PATCH 15/40] Remove redundant exception handling --- .../cameraonboarding/service/impl/CameraServiceImpl.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/CameraServiceImpl.java b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/CameraServiceImpl.java index 2da41a4..efce22b 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/CameraServiceImpl.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/CameraServiceImpl.java @@ -70,10 +70,6 @@ public void handleInitializeCamera(UUID cameraId) { public Camera getCameraById(UUID cameraId) { - if (cameraId == null) { - throw new IllegalArgumentException("Camera ID cannot be null"); - } - return cameraRepository.findById(cameraId) .orElseThrow(() -> new CameraNotFoundException(String.format("Camera not found with id: %s", cameraId))); } From 5012b036e961f108748e5dcb6d672bc6fee2b048 Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Sat, 14 Dec 2024 14:47:53 +0300 Subject: [PATCH 16/40] Refactor service methods --- .../service/impl/LightSensorService.java | 24 ++++++++----------- .../service/impl/MotionSensorService.java | 23 ++++++++---------- .../impl/TemperatureSensorService.java | 23 ++++++++---------- 3 files changed, 30 insertions(+), 40 deletions(-) diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorService.java b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorService.java index 1838799..f10ccb2 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorService.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorService.java @@ -1,7 +1,7 @@ package com.onboarding.camera.cameraonboarding.service.impl; +import com.onboarding.camera.cameraonboarding.entity.Camera; import com.onboarding.camera.cameraonboarding.entity.LightSensor; -import com.onboarding.camera.cameraonboarding.enums.SensorType; import com.onboarding.camera.cameraonboarding.exception.SensorNotCreatedException; import com.onboarding.camera.cameraonboarding.exception.SensorNotFoundException; import com.onboarding.camera.cameraonboarding.exception.SensorNotUpdatedException; @@ -30,11 +30,10 @@ public class LightSensorService implements SensorService { public LightSensor handleCreateSensor(UUID cameraId, LightSensor sensor) { try { sensor.setCamera(cameraService.getCameraById(cameraId)); - sensor.setSensorType(SensorType.LIGHT); - LightSensor savedSensor = lightSensorRepository.save(sensor); - log.info("Creating sensor: {}", sensor); - return savedSensor; - } catch (SensorNotCreatedException ex) { + LightSensor createdSensor = lightSensorRepository.save(sensor); + log.info("Creating sensor: {}", createdSensor); + return createdSensor; + } catch (Exception ex) { log.error("Failed to create sensor, camera:{}:ex:{}", cameraId, ex.getMessage()); throw new SensorNotCreatedException(String.format("Failed to create sensor: %s", ex.getMessage())); } @@ -43,8 +42,9 @@ public LightSensor handleCreateSensor(UUID cameraId, LightSensor sensor) { @Override public List handleGetSensorsByCameraId(UUID cameraId) { try { + Camera camera = cameraService.getCameraById(cameraId); log.info("Getting sensors by camera id: {}", cameraId); - return lightSensorRepository.findByCameraIdAndSensorType(cameraId, SensorType.LIGHT); + return lightSensorRepository.findLightSensorByCamera(camera); } catch (SensorNotFoundException ex) { log.error("Exception occurred while getting sensors, cameraId:{}", cameraId); throw new SensorNotFoundException(String.format("Error occurred while getting sensors: %s", ex.getMessage())); @@ -61,7 +61,7 @@ public LightSensor handleUpdateSensor(UUID sensorId, LightSensor sensor) { existingSensor.setData(sensor.getData()); log.info("Updating sensor: {}", existingSensor); return lightSensorRepository.save(existingSensor); - } catch (SensorNotUpdatedException ex) { + } catch (Exception ex) { log.error("Exception occurred while updating sensor, sensorId:{}", sensorId); throw new SensorNotUpdatedException(String.format("Error occurred while updating sensors: %s", ex.getMessage())); } @@ -69,9 +69,6 @@ public LightSensor handleUpdateSensor(UUID sensorId, LightSensor sensor) { @Override public LightSensor getSensorById(UUID sensorId) { - if (sensorId == null) { - throw new IllegalArgumentException("Sensor ID cannot be null"); - } return lightSensorRepository.findById(sensorId) .orElseThrow(() -> new SensorNotFoundException(String.format("Sensor not found with id: %s", sensorId))); @@ -80,10 +77,9 @@ public LightSensor getSensorById(UUID sensorId) { @Override public void handleDeleteSensor(UUID sensorId) { try { - LightSensor deletedSensor = getSensorById(sensorId); - log.info("Deleting sensor: {}", deletedSensor); + log.info("Deleting sensor: {}", sensorId); lightSensorRepository.deleteById(sensorId); - } catch (SensorNotUpdatedException ex) { + } catch (Exception ex) { log.error("Exception occurred while deleting sensor, sensorId:{}", sensorId); throw new SensorNotUpdatedException(String.format("Error occurred while deleting sensor: %s", ex.getMessage())); } diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/MotionSensorService.java b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/MotionSensorService.java index 5171103..4af92c5 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/MotionSensorService.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/MotionSensorService.java @@ -1,7 +1,7 @@ package com.onboarding.camera.cameraonboarding.service.impl; +import com.onboarding.camera.cameraonboarding.entity.Camera; import com.onboarding.camera.cameraonboarding.entity.MotionSensor; -import com.onboarding.camera.cameraonboarding.enums.SensorType; import com.onboarding.camera.cameraonboarding.exception.SensorNotCreatedException; import com.onboarding.camera.cameraonboarding.exception.SensorNotFoundException; import com.onboarding.camera.cameraonboarding.exception.SensorNotUpdatedException; @@ -30,10 +30,10 @@ public class MotionSensorService implements SensorService { public MotionSensor handleCreateSensor(UUID cameraId, MotionSensor sensor) { try { sensor.setCamera(cameraService.getCameraById(cameraId)); - sensor.setSensorType(SensorType.MOTION); - log.info("Creating sensor: {}", sensor); - return motionSensorRepository.save(sensor); - } catch (SensorNotCreatedException ex) { + MotionSensor createdSensor = motionSensorRepository.save(sensor); + log.info("Creating sensor: {}", createdSensor); + return createdSensor; + } catch (Exception ex) { log.error("Failed to create sensor, camera:{}:ex:{}", cameraId, ex.getMessage()); throw new SensorNotCreatedException(String.format("Failed to create sensor: %s", ex.getMessage())); } @@ -42,8 +42,9 @@ public MotionSensor handleCreateSensor(UUID cameraId, MotionSensor sensor) { @Override public List handleGetSensorsByCameraId(UUID cameraId) { try { + Camera camera = cameraService.getCameraById(cameraId); log.info("Getting sensors by camera id: {}", cameraId); - return motionSensorRepository.findByCameraIdAndSensorType(cameraId, SensorType.MOTION); + return motionSensorRepository.findMotionSensorByCamera(camera); } catch (SensorNotFoundException ex) { log.error("Exception occurred while getting sensors, cameraId:{}", cameraId); throw new SensorNotFoundException(String.format("Error occurred while getting sensors: %s", ex.getMessage())); @@ -60,7 +61,7 @@ public MotionSensor handleUpdateSensor(UUID sensorId, MotionSensor sensor) { existingSensor.setData(sensor.getData()); log.info("Updating sensor: {}", existingSensor); return motionSensorRepository.save(existingSensor); - } catch (SensorNotUpdatedException ex) { + } catch (Exception ex) { log.error("Exception occurred while updating sensor, sensorId:{}", sensorId); throw new SensorNotUpdatedException(String.format("Error occurred while updating sensors: %s", ex.getMessage())); } @@ -68,9 +69,6 @@ public MotionSensor handleUpdateSensor(UUID sensorId, MotionSensor sensor) { @Override public MotionSensor getSensorById(UUID sensorId) { - if (sensorId == null) { - throw new IllegalArgumentException("Sensor ID cannot be null"); - } return motionSensorRepository.findById(sensorId) .orElseThrow(() -> new SensorNotFoundException(String.format("Sensor not found with id: %s", sensorId))); @@ -79,10 +77,9 @@ public MotionSensor getSensorById(UUID sensorId) { @Override public void handleDeleteSensor(UUID sensorId) { try { - MotionSensor deletedSensor = getSensorById(sensorId); - log.info("Deleting sensor: {}", deletedSensor); + log.info("Deleting sensor: {}", sensorId); motionSensorRepository.deleteById(sensorId); - } catch (SensorNotUpdatedException ex) { + } catch (Exception ex) { log.error("Exception occurred while deleting sensor, sensorId:{}", sensorId); throw new SensorNotUpdatedException(String.format("Error occurred while deleting sensor: %s", ex.getMessage())); } diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/TemperatureSensorService.java b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/TemperatureSensorService.java index fc3b746..9bd4b81 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/TemperatureSensorService.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/TemperatureSensorService.java @@ -1,7 +1,7 @@ package com.onboarding.camera.cameraonboarding.service.impl; +import com.onboarding.camera.cameraonboarding.entity.Camera; import com.onboarding.camera.cameraonboarding.entity.TemperatureSensor; -import com.onboarding.camera.cameraonboarding.enums.SensorType; import com.onboarding.camera.cameraonboarding.exception.SensorNotCreatedException; import com.onboarding.camera.cameraonboarding.exception.SensorNotFoundException; import com.onboarding.camera.cameraonboarding.exception.SensorNotUpdatedException; @@ -30,10 +30,10 @@ public class TemperatureSensorService implements SensorService handleGetSensorsByCameraId(UUID cameraId) { try { + Camera camera = cameraService.getCameraById(cameraId); log.info("Getting sensors by camera id: {}", cameraId); - return temperatureSensorRepository.findByCameraIdAndSensorType(cameraId, SensorType.TEMPERATURE); + return temperatureSensorRepository.findTemperatureSensorByCamera(camera); } catch (SensorNotFoundException ex) { log.error("Exception occurred while getting sensors, cameraId:{}", cameraId); throw new SensorNotFoundException(String.format("Error occurred while getting sensors: %s", ex.getMessage())); @@ -60,7 +61,7 @@ public TemperatureSensor handleUpdateSensor(UUID sensorId, TemperatureSensor sen existingSensor.setData(sensor.getData()); log.info("Updating sensor: {}", existingSensor); return temperatureSensorRepository.save(existingSensor); - } catch (SensorNotUpdatedException ex) { + } catch (Exception ex) { log.error("Exception occurred while updating sensor, sensorId:{}", sensorId); throw new SensorNotUpdatedException(String.format("Error occurred while updating sensors: %s", ex.getMessage())); } @@ -68,9 +69,6 @@ public TemperatureSensor handleUpdateSensor(UUID sensorId, TemperatureSensor sen @Override public TemperatureSensor getSensorById(UUID sensorId) { - if (sensorId == null) { - throw new IllegalArgumentException("Sensor ID cannot be null"); - } return temperatureSensorRepository.findById(sensorId) .orElseThrow(() -> new SensorNotFoundException(String.format("Sensor not found with id: %s", sensorId))); @@ -79,10 +77,9 @@ public TemperatureSensor getSensorById(UUID sensorId) { @Override public void handleDeleteSensor(UUID sensorId) { try { - TemperatureSensor deletedSensor = getSensorById(sensorId); - log.info("Deleting sensor: {}", deletedSensor); + log.info("Deleting sensor: {}", sensorId); temperatureSensorRepository.deleteById(sensorId); - } catch (SensorNotUpdatedException ex) { + } catch (Exception ex) { log.error("Exception occurred while deleting sensor, sensorId:{}", sensorId); throw new SensorNotUpdatedException(String.format("Error occurred while deleting sensor: %s", ex.getMessage())); } From 37e3f5ad6da0cdea5f652a377f129aff3018089d Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Sat, 14 Dec 2024 15:05:41 +0300 Subject: [PATCH 17/40] Refactor repository --- .../cameraonboarding/repository/LightSensorRepository.java | 7 ++----- .../repository/MotionSensorRepository.java | 7 ++----- .../repository/TemperatureSensorRepository.java | 7 ++----- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/repository/LightSensorRepository.java b/src/main/java/com/onboarding/camera/cameraonboarding/repository/LightSensorRepository.java index d6a90e8..09868ea 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/repository/LightSensorRepository.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/repository/LightSensorRepository.java @@ -1,16 +1,13 @@ package com.onboarding.camera.cameraonboarding.repository; +import com.onboarding.camera.cameraonboarding.entity.Camera; import com.onboarding.camera.cameraonboarding.entity.LightSensor; -import com.onboarding.camera.cameraonboarding.enums.SensorType; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; import java.util.List; import java.util.UUID; public interface LightSensorRepository extends JpaRepository { - @Query("SELECT s FROM LightSensor s WHERE s.camera.camId = :cameraId AND s.sensorType = :sensorType") - List findByCameraIdAndSensorType(@Param("cameraId") UUID cameraId, @Param("sensorType") SensorType sensorType); + List findLightSensorByCamera(Camera camera); } diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/repository/MotionSensorRepository.java b/src/main/java/com/onboarding/camera/cameraonboarding/repository/MotionSensorRepository.java index 64b3cf4..b6a7b5e 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/repository/MotionSensorRepository.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/repository/MotionSensorRepository.java @@ -1,16 +1,13 @@ package com.onboarding.camera.cameraonboarding.repository; +import com.onboarding.camera.cameraonboarding.entity.Camera; import com.onboarding.camera.cameraonboarding.entity.MotionSensor; -import com.onboarding.camera.cameraonboarding.enums.SensorType; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; import java.util.List; import java.util.UUID; public interface MotionSensorRepository extends JpaRepository { - @Query("SELECT s FROM MotionSensor s WHERE s.camera.camId = :cameraId AND s.sensorType = :sensorType") - List findByCameraIdAndSensorType(@Param("cameraId") UUID cameraId, @Param("sensorType") SensorType sensorType); + List findMotionSensorByCamera(Camera camera); } diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/repository/TemperatureSensorRepository.java b/src/main/java/com/onboarding/camera/cameraonboarding/repository/TemperatureSensorRepository.java index 98f8311..ffd93f3 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/repository/TemperatureSensorRepository.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/repository/TemperatureSensorRepository.java @@ -1,16 +1,13 @@ package com.onboarding.camera.cameraonboarding.repository; +import com.onboarding.camera.cameraonboarding.entity.Camera; import com.onboarding.camera.cameraonboarding.entity.TemperatureSensor; -import com.onboarding.camera.cameraonboarding.enums.SensorType; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; import java.util.List; import java.util.UUID; public interface TemperatureSensorRepository extends JpaRepository { - @Query("SELECT s FROM TemperatureSensor s WHERE s.camera.camId = :cameraId AND s.sensorType = :sensorType") - List findByCameraIdAndSensorType(@Param("cameraId") UUID cameraId, @Param("sensorType") SensorType sensorType); + List findTemperatureSensorByCamera(Camera camera); } From ed39154634ea03b2d015de3c27dafcfc0f9ea6c8 Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Sat, 14 Dec 2024 15:08:11 +0300 Subject: [PATCH 18/40] Add enum explanation --- .../cameraonboarding/enums/SensorType.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/enums/SensorType.java b/src/main/java/com/onboarding/camera/cameraonboarding/enums/SensorType.java index fa556b9..3deff35 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/enums/SensorType.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/enums/SensorType.java @@ -1,7 +1,24 @@ package com.onboarding.camera.cameraonboarding.enums; public enum SensorType { + /** + * MOTION: Used to detect movement in the vicinity of the camera. + * This sensor is typically utilized in security systems to trigger alerts + * or initiate recordings when motion is detected. + */ MOTION, + + /** + * TEMPERATURE: Used to monitor the environmental temperature around the camera. + * This sensor can be used in smart home systems, industrial setups, or outdoor + * environments where temperature variations need to be tracked for safety or efficiency. + */ TEMPERATURE, + + /** + * LIGHT: Used to measure the intensity of light around the camera. + * This sensor can assist in adjusting the camera's exposure settings + * or determining the need for additional lighting in low-light conditions. + */ LIGHT } From 973954c447809484152a7ec3b4bdcd4a1d6384b7 Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Sat, 14 Dec 2024 15:09:27 +0300 Subject: [PATCH 19/40] Add sensors list to camera entity --- .../onboarding/camera/cameraonboarding/entity/Camera.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/entity/Camera.java b/src/main/java/com/onboarding/camera/cameraonboarding/entity/Camera.java index 389f5df..3e4e325 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/entity/Camera.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/entity/Camera.java @@ -6,6 +6,7 @@ import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; import jakarta.persistence.OneToOne; import jakarta.persistence.Table; import lombok.Data; @@ -13,6 +14,8 @@ import org.hibernate.annotations.UuidGenerator; import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; @Data @@ -54,4 +57,8 @@ public class Camera { @OneToOne(mappedBy = "camera", cascade = CascadeType.ALL, orphanRemoval = true) @JsonManagedReference private Location location; + + @OneToMany(mappedBy = "camera", cascade = CascadeType.ALL, orphanRemoval = true) + @JsonManagedReference + private List sensors = new ArrayList<>(); } From 0a42b378a546e385e5fe7069a1f4379f32c83db0 Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Sat, 14 Dec 2024 15:10:09 +0300 Subject: [PATCH 20/40] Add toString annotation --- .../camera/cameraonboarding/entity/LightSensor.java | 2 ++ .../camera/cameraonboarding/entity/MotionSensor.java | 2 ++ .../onboarding/camera/cameraonboarding/entity/Sensor.java | 7 ++++++- .../camera/cameraonboarding/entity/TemperatureSensor.java | 2 ++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/entity/LightSensor.java b/src/main/java/com/onboarding/camera/cameraonboarding/entity/LightSensor.java index 9102eb4..013a39a 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/entity/LightSensor.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/entity/LightSensor.java @@ -2,8 +2,10 @@ import jakarta.persistence.DiscriminatorValue; import jakarta.persistence.Entity; +import lombok.ToString; @Entity +@ToString @DiscriminatorValue("LIGHT") public class LightSensor extends Sensor { diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/entity/MotionSensor.java b/src/main/java/com/onboarding/camera/cameraonboarding/entity/MotionSensor.java index 4a2fca4..a120e52 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/entity/MotionSensor.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/entity/MotionSensor.java @@ -2,8 +2,10 @@ import jakarta.persistence.DiscriminatorValue; import jakarta.persistence.Entity; +import lombok.ToString; @Entity +@ToString @DiscriminatorValue("MOTION") public class MotionSensor extends Sensor { diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/entity/Sensor.java b/src/main/java/com/onboarding/camera/cameraonboarding/entity/Sensor.java index 34dfe82..6f95d96 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/entity/Sensor.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/entity/Sensor.java @@ -1,5 +1,6 @@ package com.onboarding.camera.cameraonboarding.entity; +import com.fasterxml.jackson.annotation.JsonBackReference; import com.onboarding.camera.cameraonboarding.enums.SensorType; import jakarta.persistence.Column; import jakarta.persistence.DiscriminatorColumn; @@ -9,19 +10,22 @@ import jakarta.persistence.Enumerated; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; +import jakarta.persistence.Index; import jakarta.persistence.Inheritance; import jakarta.persistence.InheritanceType; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; import lombok.Data; +import lombok.ToString; import org.hibernate.annotations.UuidGenerator; import java.util.UUID; @Data @Entity -@Table(name = "sensor_metadata") +@ToString(exclude = "camera") +@Table(name = "sensor_metadata", indexes = @Index(name = "idx_camera_id", columnList = "camera_id")) @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name = "sensor_type", discriminatorType = DiscriminatorType.STRING) public abstract class Sensor { @@ -34,6 +38,7 @@ public abstract class Sensor { @ManyToOne @JoinColumn(name = "camera_id", nullable = false) + @JsonBackReference private Camera camera; @Column(name = "name", nullable = false) diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/entity/TemperatureSensor.java b/src/main/java/com/onboarding/camera/cameraonboarding/entity/TemperatureSensor.java index 4195968..b6e9cb0 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/entity/TemperatureSensor.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/entity/TemperatureSensor.java @@ -2,8 +2,10 @@ import jakarta.persistence.DiscriminatorValue; import jakarta.persistence.Entity; +import lombok.ToString; @Entity +@ToString @DiscriminatorValue("TEMPERATURE") public class TemperatureSensor extends Sensor { From 7298ae8d0d259ba3e6ee24532b48286857178e18 Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Sat, 14 Dec 2024 15:10:52 +0300 Subject: [PATCH 21/40] Add toString annotation --- .../com/onboarding/camera/cameraonboarding/dto/SensorDto.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/dto/SensorDto.java b/src/main/java/com/onboarding/camera/cameraonboarding/dto/SensorDto.java index 4891045..842513c 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/dto/SensorDto.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/dto/SensorDto.java @@ -7,8 +7,10 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import lombok.ToString; @Data +@ToString @NoArgsConstructor @AllArgsConstructor public class SensorDto { From 15483c03ad60445820b1bd9269c14d8a4ddc326c Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Sat, 14 Dec 2024 15:11:35 +0300 Subject: [PATCH 22/40] Refactor conversion methods --- .../converter/SensorDtoConverter.java | 68 ++++++++----------- 1 file changed, 30 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverter.java b/src/main/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverter.java index 690eeb6..039c6f9 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverter.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverter.java @@ -10,54 +10,46 @@ import com.onboarding.camera.cameraonboarding.exception.SensorMismatchException; import org.springframework.stereotype.Component; -import java.util.stream.Stream; - @Component public class SensorDtoConverter { public MotionSensor toMotionEntity(SensorDto sensorDto) { - return Stream.of(sensorDto) - .filter(dto -> dto.getSensorType() == SensorType.MOTION) - .map(dto -> { - MotionSensor sensorMetadata = new MotionSensor(); - sensorMetadata.setName(dto.getName()); - sensorMetadata.setVersion(dto.getVersion()); - sensorMetadata.setSensorType(dto.getSensorType()); - sensorMetadata.setData(dto.getData()); - return sensorMetadata; - }) - .findFirst() - .orElseThrow(() -> new SensorMismatchException("Invalid sensor type for MotionSensor")); + if (sensorDto.getSensorType() != SensorType.MOTION) { + throw new SensorMismatchException("Invalid sensor type for MotionSensor"); + } + + MotionSensor sensorMetadata = new MotionSensor(); + sensorMetadata.setName(sensorDto.getName()); + sensorMetadata.setVersion(sensorDto.getVersion()); + sensorMetadata.setSensorType(sensorDto.getSensorType()); + sensorMetadata.setData(sensorDto.getData()); + return sensorMetadata; } public LightSensor toLightEntity(SensorDto sensorDto) { - return Stream.of(sensorDto) - .filter(dto -> dto.getSensorType() == SensorType.LIGHT) - .map(dto -> { - LightSensor sensorMetadata = new LightSensor(); - sensorMetadata.setName(dto.getName()); - sensorMetadata.setVersion(dto.getVersion()); - sensorMetadata.setSensorType(dto.getSensorType()); - sensorMetadata.setData(dto.getData()); - return sensorMetadata; - }) - .findFirst() - .orElseThrow(() -> new SensorMismatchException("Invalid sensor type for LightSensor")); + if (sensorDto.getSensorType() != SensorType.LIGHT) { + throw new SensorMismatchException("Invalid sensor type for LightSensor"); + } + + LightSensor sensorMetadata = new LightSensor(); + sensorMetadata.setName(sensorDto.getName()); + sensorMetadata.setVersion(sensorDto.getVersion()); + sensorMetadata.setSensorType(sensorDto.getSensorType()); + sensorMetadata.setData(sensorDto.getData()); + return sensorMetadata; } public TemperatureSensor toTemperatureEntity(SensorDto sensorDto) { - return Stream.of(sensorDto) - .filter(dto -> dto.getSensorType() == SensorType.TEMPERATURE) - .map(dto -> { - TemperatureSensor sensorMetadata = new TemperatureSensor(); - sensorMetadata.setName(dto.getName()); - sensorMetadata.setVersion(dto.getVersion()); - sensorMetadata.setSensorType(dto.getSensorType()); - sensorMetadata.setData(dto.getData()); - return sensorMetadata; - }) - .findFirst() - .orElseThrow(() -> new SensorMismatchException("Invalid sensor type for TemperatureSensor")); + if (sensorDto.getSensorType() != SensorType.TEMPERATURE) { + throw new SensorMismatchException("Invalid sensor type for TemperatureSensor"); + } + + TemperatureSensor sensorMetadata = new TemperatureSensor(); + sensorMetadata.setName(sensorDto.getName()); + sensorMetadata.setVersion(sensorDto.getVersion()); + sensorMetadata.setSensorType(sensorDto.getSensorType()); + sensorMetadata.setData(sensorDto.getData()); + return sensorMetadata; } public SensorResponse toSensorResponse(Sensor sensor) { From 71eceac3fc291a5ad8e702c24cb0a4f904bc4400 Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Sat, 14 Dec 2024 15:12:36 +0300 Subject: [PATCH 23/40] Remove redundant path variable --- .../cameraonboarding/controller/LightSensorController.java | 2 -- .../cameraonboarding/controller/MotionSensorController.java | 2 -- .../controller/TemperatureSensorController.java | 2 -- 3 files changed, 6 deletions(-) diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/controller/LightSensorController.java b/src/main/java/com/onboarding/camera/cameraonboarding/controller/LightSensorController.java index 30eb81c..158cf01 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/controller/LightSensorController.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/controller/LightSensorController.java @@ -52,7 +52,6 @@ public ResponseEntity> getLightSensors( @PutMapping("/{sensorId}") public ResponseEntity updateLightSensor( - @PathVariable UUID cameraId, @PathVariable UUID sensorId, @Valid @RequestBody SensorDto sensorDto) { @@ -64,7 +63,6 @@ public ResponseEntity updateLightSensor( @DeleteMapping("/{sensorId}") public ResponseEntity deleteLightSensor( - @PathVariable UUID cameraId, @PathVariable UUID sensorId) { lightSensorService.handleDeleteSensor(sensorId); diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/controller/MotionSensorController.java b/src/main/java/com/onboarding/camera/cameraonboarding/controller/MotionSensorController.java index 3a1f7fb..d058fc7 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/controller/MotionSensorController.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/controller/MotionSensorController.java @@ -52,7 +52,6 @@ public ResponseEntity> getMotionSensors( @PutMapping("/{sensorId}") public ResponseEntity updateMotionSensor( - @PathVariable UUID cameraId, @PathVariable UUID sensorId, @Valid @RequestBody SensorDto sensorDto) { @@ -64,7 +63,6 @@ public ResponseEntity updateMotionSensor( @DeleteMapping("/{sensorId}") public ResponseEntity deleteMotionSensor( - @PathVariable UUID cameraId, @PathVariable UUID sensorId) { motionSensorService.handleDeleteSensor(sensorId); diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/controller/TemperatureSensorController.java b/src/main/java/com/onboarding/camera/cameraonboarding/controller/TemperatureSensorController.java index d1e5a30..2e218b0 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/controller/TemperatureSensorController.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/controller/TemperatureSensorController.java @@ -51,7 +51,6 @@ public ResponseEntity> getTemperatureSensors( @PutMapping("/{sensorId}") public ResponseEntity updateTemperatureSensor( - @PathVariable UUID cameraId, @PathVariable UUID sensorId, @Valid @RequestBody SensorDto sensorDto) { @@ -63,7 +62,6 @@ public ResponseEntity updateTemperatureSensor( @DeleteMapping("/{sensorId}") public ResponseEntity deleteTemperatureSensor( - @PathVariable UUID cameraId, @PathVariable UUID sensorId) { temperatureSensorService.handleDeleteSensor(sensorId); From 961d86ca64ed59047aedc40f3cea8bdb053312e3 Mon Sep 17 00:00:00 2001 From: Selahattin Sert Date: Mon, 9 Dec 2024 02:24:25 +0300 Subject: [PATCH 24/40] Include db changelog v3 --- src/main/resources/db/changelog/changelog-master.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/db/changelog/changelog-master.xml b/src/main/resources/db/changelog/changelog-master.xml index fa0bdc8..7d48782 100644 --- a/src/main/resources/db/changelog/changelog-master.xml +++ b/src/main/resources/db/changelog/changelog-master.xml @@ -7,5 +7,6 @@ + \ No newline at end of file From 3debae9743d2d6bffc1d5dda38ed53d28c58d5b2 Mon Sep 17 00:00:00 2001 From: Selahattin <98191442+SelahattinSert@users.noreply.github.com> Date: Thu, 19 Dec 2024 13:21:48 +0300 Subject: [PATCH 25/40] Fix test case issue --- .../cameraonboarding/service/CameraServiceImplTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/onboarding/camera/cameraonboarding/service/CameraServiceImplTest.java b/src/test/java/com/onboarding/camera/cameraonboarding/service/CameraServiceImplTest.java index 753084c..f8149a0 100644 --- a/src/test/java/com/onboarding/camera/cameraonboarding/service/CameraServiceImplTest.java +++ b/src/test/java/com/onboarding/camera/cameraonboarding/service/CameraServiceImplTest.java @@ -245,11 +245,11 @@ void expect_getCameraById_toGetCamera() { } @Test - void expect_getCameraById_withNullCameraId_toThrowIllegalArgumentException() { + void expect_getCameraById_withNonExistingUUID_toThrowCameraNotFoundException() { // act and assert - Assertions.assertThatThrownBy(() -> cameraService.getCameraById(null)) - .isInstanceOf(IllegalArgumentException.class); + Assertions.assertThatThrownBy(() -> cameraService.getCameraById(NON_EXISTING_UUID)) + .isInstanceOf(CameraNotFoundException.class); Mockito.verify(cameraRepository, Mockito.never()).findById(CAMERA_ID); } From d13a3ccfd5299dae043ce9271efb0e1e71640829 Mon Sep 17 00:00:00 2001 From: Selahattin <98191442+SelahattinSert@users.noreply.github.com> Date: Fri, 20 Dec 2024 03:30:02 +0300 Subject: [PATCH 26/40] Utilize path variable camera id --- .../controller/LightSensorController.java | 8 ++++---- .../controller/MotionSensorController.java | 8 ++++---- .../controller/TemperatureSensorController.java | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/controller/LightSensorController.java b/src/main/java/com/onboarding/camera/cameraonboarding/controller/LightSensorController.java index 158cf01..55277e8 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/controller/LightSensorController.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/controller/LightSensorController.java @@ -53,19 +53,19 @@ public ResponseEntity> getLightSensors( @PutMapping("/{sensorId}") public ResponseEntity updateLightSensor( @PathVariable UUID sensorId, - @Valid @RequestBody SensorDto sensorDto) { + @Valid @RequestBody SensorDto sensorDto, @PathVariable UUID cameraId) { LightSensor sensorMetadata = sensorDtoConverter.toLightEntity(sensorDto); - LightSensor updatedSensor = lightSensorService.handleUpdateSensor(sensorId, sensorMetadata); + LightSensor updatedSensor = lightSensorService.handleUpdateSensor(cameraId, sensorId, sensorMetadata); SensorResponse sensorResponse = sensorDtoConverter.toSensorResponse(updatedSensor); return ResponseEntity.ok(sensorResponse); } @DeleteMapping("/{sensorId}") public ResponseEntity deleteLightSensor( - @PathVariable UUID sensorId) { + @PathVariable UUID sensorId, @PathVariable UUID cameraId) { - lightSensorService.handleDeleteSensor(sensorId); + lightSensorService.handleDeleteSensor(cameraId, sensorId); return ResponseEntity.noContent().build(); } } diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/controller/MotionSensorController.java b/src/main/java/com/onboarding/camera/cameraonboarding/controller/MotionSensorController.java index d058fc7..3b6b986 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/controller/MotionSensorController.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/controller/MotionSensorController.java @@ -53,19 +53,19 @@ public ResponseEntity> getMotionSensors( @PutMapping("/{sensorId}") public ResponseEntity updateMotionSensor( @PathVariable UUID sensorId, - @Valid @RequestBody SensorDto sensorDto) { + @Valid @RequestBody SensorDto sensorDto, @PathVariable UUID cameraId) { MotionSensor motionSensor = sensorDtoConverter.toMotionEntity(sensorDto); - MotionSensor updatedSensor = motionSensorService.handleUpdateSensor(sensorId, motionSensor); + MotionSensor updatedSensor = motionSensorService.handleUpdateSensor(cameraId, sensorId, motionSensor); SensorResponse sensorResponse = sensorDtoConverter.toSensorResponse(updatedSensor); return ResponseEntity.ok(sensorResponse); } @DeleteMapping("/{sensorId}") public ResponseEntity deleteMotionSensor( - @PathVariable UUID sensorId) { + @PathVariable UUID sensorId, @PathVariable UUID cameraId) { - motionSensorService.handleDeleteSensor(sensorId); + motionSensorService.handleDeleteSensor(cameraId, sensorId); return ResponseEntity.noContent().build(); } } diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/controller/TemperatureSensorController.java b/src/main/java/com/onboarding/camera/cameraonboarding/controller/TemperatureSensorController.java index 2e218b0..20c5c04 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/controller/TemperatureSensorController.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/controller/TemperatureSensorController.java @@ -52,19 +52,19 @@ public ResponseEntity> getTemperatureSensors( @PutMapping("/{sensorId}") public ResponseEntity updateTemperatureSensor( @PathVariable UUID sensorId, - @Valid @RequestBody SensorDto sensorDto) { + @Valid @RequestBody SensorDto sensorDto, @PathVariable UUID cameraId) { TemperatureSensor sensorMetadata = sensorDtoConverter.toTemperatureEntity(sensorDto); - TemperatureSensor updatedSensor = temperatureSensorService.handleUpdateSensor(sensorId, sensorMetadata); + TemperatureSensor updatedSensor = temperatureSensorService.handleUpdateSensor(cameraId, sensorId, sensorMetadata); SensorResponse sensorResponse = sensorDtoConverter.toSensorResponse(updatedSensor); return ResponseEntity.ok(sensorResponse); } @DeleteMapping("/{sensorId}") public ResponseEntity deleteTemperatureSensor( - @PathVariable UUID sensorId) { + @PathVariable UUID sensorId, @PathVariable UUID cameraId) { - temperatureSensorService.handleDeleteSensor(sensorId); + temperatureSensorService.handleDeleteSensor(cameraId, sensorId); return ResponseEntity.noContent().build(); } } From 37aa5462dbe2915e69f9a1d4391a94cb1e93bc0f Mon Sep 17 00:00:00 2001 From: Selahattin <98191442+SelahattinSert@users.noreply.github.com> Date: Fri, 20 Dec 2024 03:32:06 +0300 Subject: [PATCH 27/40] Add list of sensors to camera response --- .../converter/CameraDtoConverter.java | 15 +++++++++++++++ .../cameraonboarding/dto/CameraResponse.java | 3 +++ 2 files changed, 18 insertions(+) diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/converter/CameraDtoConverter.java b/src/main/java/com/onboarding/camera/cameraonboarding/converter/CameraDtoConverter.java index b8c1744..9addaec 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/converter/CameraDtoConverter.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/converter/CameraDtoConverter.java @@ -2,9 +2,12 @@ import com.onboarding.camera.cameraonboarding.dto.CameraDto; import com.onboarding.camera.cameraonboarding.dto.CameraResponse; +import com.onboarding.camera.cameraonboarding.dto.SensorResponse; import com.onboarding.camera.cameraonboarding.entity.Camera; import org.springframework.stereotype.Component; +import java.util.stream.Collectors; + @Component public class CameraDtoConverter { @@ -20,6 +23,18 @@ public CameraResponse toCameraResponse(Camera camera) { response.setCameraId(camera.getCamId()); response.setCameraName(camera.getCameraName()); response.setFirmwareVersion(camera.getFirmwareVersion()); + response.setSensors(camera.getSensors() + .stream() + .map(sensor -> { + SensorResponse sensorResponse = new SensorResponse(); + sensorResponse.setId(sensor.getId()); + sensorResponse.setName(sensor.getName()); + sensorResponse.setVersion(sensor.getVersion()); + sensorResponse.setSensorType(sensor.getSensorType()); + sensorResponse.setData(sensor.getData()); + return sensorResponse; + }) + .collect(Collectors.toList())); return response; } } diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/dto/CameraResponse.java b/src/main/java/com/onboarding/camera/cameraonboarding/dto/CameraResponse.java index 6aac830..3e45431 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/dto/CameraResponse.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/dto/CameraResponse.java @@ -1,6 +1,8 @@ package com.onboarding.camera.cameraonboarding.dto; import lombok.Data; + +import java.util.List; import java.util.UUID; @Data @@ -8,4 +10,5 @@ public class CameraResponse { private UUID cameraId; private String cameraName; private String firmwareVersion; + private List sensors; } From 058b0f573bd1a76eaef5d586cc3db22aa109cb72 Mon Sep 17 00:00:00 2001 From: Selahattin <98191442+SelahattinSert@users.noreply.github.com> Date: Fri, 20 Dec 2024 03:32:29 +0300 Subject: [PATCH 28/40] Refactor sensor methods --- .../service/SensorService.java | 6 ++- .../service/impl/LightSensorService.java | 45 ++++++++++++++++--- .../service/impl/MotionSensorService.java | 45 ++++++++++++++++--- .../impl/TemperatureSensorService.java | 45 ++++++++++++++++--- 4 files changed, 121 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/service/SensorService.java b/src/main/java/com/onboarding/camera/cameraonboarding/service/SensorService.java index dac83ca..fc470d2 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/service/SensorService.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/service/SensorService.java @@ -33,12 +33,13 @@ public interface SensorService { /** * this method is used for update sensor by sensor ID * + * @param cameraId camera id * @param sensorId sensor id * @param sensor sensor * @return Sensor updated sensor * @throws SensorNotUpdatedException if unexpected error occurs while updating sensor */ - T handleUpdateSensor(UUID sensorId, T sensor); + T handleUpdateSensor(UUID cameraId, UUID sensorId, T sensor); /** * this method is used for get sensor by sensor ID @@ -52,8 +53,9 @@ public interface SensorService { /** * this method is used for deleting sensor by sensor ID * + * @param cameraId sensor id * @param sensorId sensor id * @throws SensorNotUpdatedException if unexpected error occurs while deleting sensor */ - void handleDeleteSensor(UUID sensorId); + void handleDeleteSensor(UUID cameraId, UUID sensorId); } diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorService.java b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorService.java index f10ccb2..9f5c6ae 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorService.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorService.java @@ -2,6 +2,7 @@ import com.onboarding.camera.cameraonboarding.entity.Camera; import com.onboarding.camera.cameraonboarding.entity.LightSensor; +import com.onboarding.camera.cameraonboarding.exception.CameraNotFoundException; import com.onboarding.camera.cameraonboarding.exception.SensorNotCreatedException; import com.onboarding.camera.cameraonboarding.exception.SensorNotFoundException; import com.onboarding.camera.cameraonboarding.exception.SensorNotUpdatedException; @@ -33,6 +34,9 @@ public LightSensor handleCreateSensor(UUID cameraId, LightSensor sensor) { LightSensor createdSensor = lightSensorRepository.save(sensor); log.info("Creating sensor: {}", createdSensor); return createdSensor; + } catch (CameraNotFoundException ex) { + log.error("Camera not found, cameraId:{}", cameraId); + throw ex; } catch (Exception ex) { log.error("Failed to create sensor, camera:{}:ex:{}", cameraId, ex.getMessage()); throw new SensorNotCreatedException(String.format("Failed to create sensor: %s", ex.getMessage())); @@ -45,7 +49,10 @@ public List handleGetSensorsByCameraId(UUID cameraId) { Camera camera = cameraService.getCameraById(cameraId); log.info("Getting sensors by camera id: {}", cameraId); return lightSensorRepository.findLightSensorByCamera(camera); - } catch (SensorNotFoundException ex) { + } catch (CameraNotFoundException ex) { + log.error("Camera not found, cameraId:{}", cameraId); + throw ex; + } catch (Exception ex) { log.error("Exception occurred while getting sensors, cameraId:{}", cameraId); throw new SensorNotFoundException(String.format("Error occurred while getting sensors: %s", ex.getMessage())); } @@ -53,14 +60,26 @@ public List handleGetSensorsByCameraId(UUID cameraId) { @Override @Transactional - public LightSensor handleUpdateSensor(UUID sensorId, LightSensor sensor) { + public LightSensor handleUpdateSensor(UUID cameraId, UUID sensorId, LightSensor sensor) { try { - LightSensor existingSensor = getSensorById(sensorId); + Camera camera = cameraService.getCameraById(cameraId); + LightSensor existingSensor = camera.getSensors().stream() + .filter(s -> s.getId().equals(sensorId) && s instanceof LightSensor) + .map(s -> (LightSensor) s) + .findFirst() + .orElseThrow(() -> new SensorNotFoundException(String.format("Sensor not found with id: %s", sensorId))); + existingSensor.setName(sensor.getName()); existingSensor.setVersion(sensor.getVersion()); existingSensor.setData(sensor.getData()); log.info("Updating sensor: {}", existingSensor); return lightSensorRepository.save(existingSensor); + } catch (SensorNotFoundException ex) { + log.error("Sensor not found while updating, sensorId: {}", sensorId); + throw ex; + } catch (CameraNotFoundException ex) { + log.error("Camera not found, cameraId:{}", cameraId); + throw ex; } catch (Exception ex) { log.error("Exception occurred while updating sensor, sensorId:{}", sensorId); throw new SensorNotUpdatedException(String.format("Error occurred while updating sensors: %s", ex.getMessage())); @@ -75,10 +94,24 @@ public LightSensor getSensorById(UUID sensorId) { } @Override - public void handleDeleteSensor(UUID sensorId) { + public void handleDeleteSensor(UUID cameraId, UUID sensorId) { try { - log.info("Deleting sensor: {}", sensorId); - lightSensorRepository.deleteById(sensorId); + Camera camera = cameraService.getCameraById(cameraId); + LightSensor sensor = camera.getSensors().stream() + .filter(s -> s.getId().equals(sensorId) && s instanceof LightSensor) + .map(s -> (LightSensor) s) + .findFirst() + .orElseThrow(() -> new SensorNotFoundException(String.format("Sensor not found with id: %s", sensorId))); + + camera.getSensors().remove(sensor); + lightSensorRepository.delete(sensor); + log.info("Deleted sensor: {}", sensorId); + } catch (CameraNotFoundException ex) { + log.error("Camera not found, cameraId:{}", cameraId); + throw ex; + } catch (SensorNotFoundException ex) { + log.error("Sensor not found while deleting, sensorId: {}", sensorId); + throw ex; } catch (Exception ex) { log.error("Exception occurred while deleting sensor, sensorId:{}", sensorId); throw new SensorNotUpdatedException(String.format("Error occurred while deleting sensor: %s", ex.getMessage())); diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/MotionSensorService.java b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/MotionSensorService.java index 4af92c5..5f7b6fc 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/MotionSensorService.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/MotionSensorService.java @@ -2,6 +2,7 @@ import com.onboarding.camera.cameraonboarding.entity.Camera; import com.onboarding.camera.cameraonboarding.entity.MotionSensor; +import com.onboarding.camera.cameraonboarding.exception.CameraNotFoundException; import com.onboarding.camera.cameraonboarding.exception.SensorNotCreatedException; import com.onboarding.camera.cameraonboarding.exception.SensorNotFoundException; import com.onboarding.camera.cameraonboarding.exception.SensorNotUpdatedException; @@ -33,6 +34,9 @@ public MotionSensor handleCreateSensor(UUID cameraId, MotionSensor sensor) { MotionSensor createdSensor = motionSensorRepository.save(sensor); log.info("Creating sensor: {}", createdSensor); return createdSensor; + } catch (CameraNotFoundException ex) { + log.error("Camera not found, cameraId:{}", cameraId); + throw ex; } catch (Exception ex) { log.error("Failed to create sensor, camera:{}:ex:{}", cameraId, ex.getMessage()); throw new SensorNotCreatedException(String.format("Failed to create sensor: %s", ex.getMessage())); @@ -45,7 +49,10 @@ public List handleGetSensorsByCameraId(UUID cameraId) { Camera camera = cameraService.getCameraById(cameraId); log.info("Getting sensors by camera id: {}", cameraId); return motionSensorRepository.findMotionSensorByCamera(camera); - } catch (SensorNotFoundException ex) { + } catch (CameraNotFoundException ex) { + log.error("Camera not found, cameraId:{}", cameraId); + throw ex; + } catch (Exception ex) { log.error("Exception occurred while getting sensors, cameraId:{}", cameraId); throw new SensorNotFoundException(String.format("Error occurred while getting sensors: %s", ex.getMessage())); } @@ -53,14 +60,26 @@ public List handleGetSensorsByCameraId(UUID cameraId) { @Override @Transactional - public MotionSensor handleUpdateSensor(UUID sensorId, MotionSensor sensor) { + public MotionSensor handleUpdateSensor(UUID cameraId, UUID sensorId, MotionSensor sensor) { try { - MotionSensor existingSensor = getSensorById(sensorId); + Camera camera = cameraService.getCameraById(cameraId); + MotionSensor existingSensor = camera.getSensors().stream() + .filter(s -> s.getId().equals(sensorId) && s instanceof MotionSensor) + .map(s -> (MotionSensor) s) + .findFirst() + .orElseThrow(() -> new SensorNotFoundException(String.format("Sensor not found with id: %s", sensorId))); + existingSensor.setName(sensor.getName()); existingSensor.setVersion(sensor.getVersion()); existingSensor.setData(sensor.getData()); log.info("Updating sensor: {}", existingSensor); return motionSensorRepository.save(existingSensor); + } catch (CameraNotFoundException ex) { + log.error("Camera not found, cameraId:{}", cameraId); + throw ex; + } catch (SensorNotFoundException ex) { + log.error("Sensor not found while updating, sensorId: {}", sensorId); + throw ex; } catch (Exception ex) { log.error("Exception occurred while updating sensor, sensorId:{}", sensorId); throw new SensorNotUpdatedException(String.format("Error occurred while updating sensors: %s", ex.getMessage())); @@ -75,10 +94,24 @@ public MotionSensor getSensorById(UUID sensorId) { } @Override - public void handleDeleteSensor(UUID sensorId) { + public void handleDeleteSensor(UUID cameraId, UUID sensorId) { try { - log.info("Deleting sensor: {}", sensorId); - motionSensorRepository.deleteById(sensorId); + Camera camera = cameraService.getCameraById(cameraId); + MotionSensor sensor = camera.getSensors().stream() + .filter(s -> s.getId().equals(sensorId) && s instanceof MotionSensor) + .map(s -> (MotionSensor) s) + .findFirst() + .orElseThrow(() -> new SensorNotFoundException(String.format("Sensor not found with id: %s", sensorId))); + + camera.getSensors().remove(sensor); + motionSensorRepository.delete(sensor); + log.info("Deleted sensor: {}", sensorId); + } catch (CameraNotFoundException ex) { + log.error("Camera not found, cameraId:{}", cameraId); + throw ex; + } catch (SensorNotFoundException ex) { + log.error("Sensor not found while deleting, sensorId: {}", sensorId); + throw ex; } catch (Exception ex) { log.error("Exception occurred while deleting sensor, sensorId:{}", sensorId); throw new SensorNotUpdatedException(String.format("Error occurred while deleting sensor: %s", ex.getMessage())); diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/TemperatureSensorService.java b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/TemperatureSensorService.java index 9bd4b81..471f199 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/TemperatureSensorService.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/TemperatureSensorService.java @@ -2,6 +2,7 @@ import com.onboarding.camera.cameraonboarding.entity.Camera; import com.onboarding.camera.cameraonboarding.entity.TemperatureSensor; +import com.onboarding.camera.cameraonboarding.exception.CameraNotFoundException; import com.onboarding.camera.cameraonboarding.exception.SensorNotCreatedException; import com.onboarding.camera.cameraonboarding.exception.SensorNotFoundException; import com.onboarding.camera.cameraonboarding.exception.SensorNotUpdatedException; @@ -33,6 +34,9 @@ public TemperatureSensor handleCreateSensor(UUID cameraId, TemperatureSensor sen TemperatureSensor createdSensor = temperatureSensorRepository.save(sensor); log.info("Creating sensor: {}", createdSensor); return createdSensor; + } catch (CameraNotFoundException ex) { + log.error("Camera not found, cameraId:{}", cameraId); + throw ex; } catch (Exception ex) { log.error("Failed to create sensor, camera:{}:ex:{}", cameraId, ex.getMessage()); throw new SensorNotCreatedException(String.format("Failed to create sensor: %s", ex.getMessage())); @@ -45,7 +49,10 @@ public List handleGetSensorsByCameraId(UUID cameraId) { Camera camera = cameraService.getCameraById(cameraId); log.info("Getting sensors by camera id: {}", cameraId); return temperatureSensorRepository.findTemperatureSensorByCamera(camera); - } catch (SensorNotFoundException ex) { + } catch (CameraNotFoundException ex) { + log.error("Camera not found, cameraId:{}", cameraId); + throw ex; + } catch (Exception ex) { log.error("Exception occurred while getting sensors, cameraId:{}", cameraId); throw new SensorNotFoundException(String.format("Error occurred while getting sensors: %s", ex.getMessage())); } @@ -53,14 +60,26 @@ public List handleGetSensorsByCameraId(UUID cameraId) { @Override @Transactional - public TemperatureSensor handleUpdateSensor(UUID sensorId, TemperatureSensor sensor) { + public TemperatureSensor handleUpdateSensor(UUID cameraId, UUID sensorId, TemperatureSensor sensor) { try { - TemperatureSensor existingSensor = getSensorById(sensorId); + Camera camera = cameraService.getCameraById(cameraId); + TemperatureSensor existingSensor = camera.getSensors().stream() + .filter(s -> s.getId().equals(sensorId) && s instanceof TemperatureSensor) + .map(s -> (TemperatureSensor) s) + .findFirst() + .orElseThrow(() -> new SensorNotFoundException(String.format("Sensor not found with id: %s", sensorId))); + existingSensor.setName(sensor.getName()); existingSensor.setVersion(sensor.getVersion()); existingSensor.setData(sensor.getData()); log.info("Updating sensor: {}", existingSensor); return temperatureSensorRepository.save(existingSensor); + } catch (CameraNotFoundException ex) { + log.error("Camera not found, cameraId:{}", cameraId); + throw ex; + } catch (SensorNotFoundException ex) { + log.error("Sensor not found while updating, sensorId: {}", sensorId); + throw ex; } catch (Exception ex) { log.error("Exception occurred while updating sensor, sensorId:{}", sensorId); throw new SensorNotUpdatedException(String.format("Error occurred while updating sensors: %s", ex.getMessage())); @@ -75,10 +94,24 @@ public TemperatureSensor getSensorById(UUID sensorId) { } @Override - public void handleDeleteSensor(UUID sensorId) { + public void handleDeleteSensor(UUID cameraId, UUID sensorId) { try { - log.info("Deleting sensor: {}", sensorId); - temperatureSensorRepository.deleteById(sensorId); + Camera camera = cameraService.getCameraById(cameraId); + TemperatureSensor sensor = camera.getSensors().stream() + .filter(s -> s.getId().equals(sensorId) && s instanceof TemperatureSensor) + .map(s -> (TemperatureSensor) s) + .findFirst() + .orElseThrow(() -> new SensorNotFoundException(String.format("Sensor not found with id: %s", sensorId))); + + camera.getSensors().remove(sensor); + temperatureSensorRepository.delete(sensor); + log.info("Deleted sensor: {}", sensorId); + } catch (CameraNotFoundException ex) { + log.error("Camera not found, cameraId:{}", cameraId); + throw ex; + } catch (SensorNotFoundException ex) { + log.error("Sensor not found while deleting, sensorId: {}", sensorId); + throw ex; } catch (Exception ex) { log.error("Exception occurred while deleting sensor, sensorId:{}", sensorId); throw new SensorNotUpdatedException(String.format("Error occurred while deleting sensor: %s", ex.getMessage())); From 9f013e529de4f6fdfd5bf28938cda16aa64401ef Mon Sep 17 00:00:00 2001 From: Selahattin <98191442+SelahattinSert@users.noreply.github.com> Date: Tue, 24 Dec 2024 00:48:57 +0300 Subject: [PATCH 29/40] Refactor sensor receive method --- .../cameraonboarding/service/impl/LightSensorService.java | 5 +++-- .../cameraonboarding/service/impl/MotionSensorService.java | 5 +++-- .../service/impl/TemperatureSensorService.java | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorService.java b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorService.java index 9f5c6ae..3926a2d 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorService.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorService.java @@ -2,6 +2,7 @@ import com.onboarding.camera.cameraonboarding.entity.Camera; import com.onboarding.camera.cameraonboarding.entity.LightSensor; +import com.onboarding.camera.cameraonboarding.enums.SensorType; import com.onboarding.camera.cameraonboarding.exception.CameraNotFoundException; import com.onboarding.camera.cameraonboarding.exception.SensorNotCreatedException; import com.onboarding.camera.cameraonboarding.exception.SensorNotFoundException; @@ -64,7 +65,7 @@ public LightSensor handleUpdateSensor(UUID cameraId, UUID sensorId, LightSensor try { Camera camera = cameraService.getCameraById(cameraId); LightSensor existingSensor = camera.getSensors().stream() - .filter(s -> s.getId().equals(sensorId) && s instanceof LightSensor) + .filter(s -> s.getId().equals(sensorId) && s.getSensorType().equals(SensorType.LIGHT)) .map(s -> (LightSensor) s) .findFirst() .orElseThrow(() -> new SensorNotFoundException(String.format("Sensor not found with id: %s", sensorId))); @@ -98,7 +99,7 @@ public void handleDeleteSensor(UUID cameraId, UUID sensorId) { try { Camera camera = cameraService.getCameraById(cameraId); LightSensor sensor = camera.getSensors().stream() - .filter(s -> s.getId().equals(sensorId) && s instanceof LightSensor) + .filter(s -> s.getId().equals(sensorId) && s.getSensorType().equals(SensorType.LIGHT)) .map(s -> (LightSensor) s) .findFirst() .orElseThrow(() -> new SensorNotFoundException(String.format("Sensor not found with id: %s", sensorId))); diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/MotionSensorService.java b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/MotionSensorService.java index 5f7b6fc..c7be36f 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/MotionSensorService.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/MotionSensorService.java @@ -2,6 +2,7 @@ import com.onboarding.camera.cameraonboarding.entity.Camera; import com.onboarding.camera.cameraonboarding.entity.MotionSensor; +import com.onboarding.camera.cameraonboarding.enums.SensorType; import com.onboarding.camera.cameraonboarding.exception.CameraNotFoundException; import com.onboarding.camera.cameraonboarding.exception.SensorNotCreatedException; import com.onboarding.camera.cameraonboarding.exception.SensorNotFoundException; @@ -64,7 +65,7 @@ public MotionSensor handleUpdateSensor(UUID cameraId, UUID sensorId, MotionSenso try { Camera camera = cameraService.getCameraById(cameraId); MotionSensor existingSensor = camera.getSensors().stream() - .filter(s -> s.getId().equals(sensorId) && s instanceof MotionSensor) + .filter(s -> s.getId().equals(sensorId) && s.getSensorType().equals(SensorType.MOTION)) .map(s -> (MotionSensor) s) .findFirst() .orElseThrow(() -> new SensorNotFoundException(String.format("Sensor not found with id: %s", sensorId))); @@ -98,7 +99,7 @@ public void handleDeleteSensor(UUID cameraId, UUID sensorId) { try { Camera camera = cameraService.getCameraById(cameraId); MotionSensor sensor = camera.getSensors().stream() - .filter(s -> s.getId().equals(sensorId) && s instanceof MotionSensor) + .filter(s -> s.getId().equals(sensorId) && s.getSensorType().equals(SensorType.MOTION)) .map(s -> (MotionSensor) s) .findFirst() .orElseThrow(() -> new SensorNotFoundException(String.format("Sensor not found with id: %s", sensorId))); diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/TemperatureSensorService.java b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/TemperatureSensorService.java index 471f199..f1a0835 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/TemperatureSensorService.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/service/impl/TemperatureSensorService.java @@ -2,6 +2,7 @@ import com.onboarding.camera.cameraonboarding.entity.Camera; import com.onboarding.camera.cameraonboarding.entity.TemperatureSensor; +import com.onboarding.camera.cameraonboarding.enums.SensorType; import com.onboarding.camera.cameraonboarding.exception.CameraNotFoundException; import com.onboarding.camera.cameraonboarding.exception.SensorNotCreatedException; import com.onboarding.camera.cameraonboarding.exception.SensorNotFoundException; @@ -64,7 +65,7 @@ public TemperatureSensor handleUpdateSensor(UUID cameraId, UUID sensorId, Temper try { Camera camera = cameraService.getCameraById(cameraId); TemperatureSensor existingSensor = camera.getSensors().stream() - .filter(s -> s.getId().equals(sensorId) && s instanceof TemperatureSensor) + .filter(s -> s.getId().equals(sensorId) && s.getSensorType().equals(SensorType.TEMPERATURE)) .map(s -> (TemperatureSensor) s) .findFirst() .orElseThrow(() -> new SensorNotFoundException(String.format("Sensor not found with id: %s", sensorId))); @@ -98,7 +99,7 @@ public void handleDeleteSensor(UUID cameraId, UUID sensorId) { try { Camera camera = cameraService.getCameraById(cameraId); TemperatureSensor sensor = camera.getSensors().stream() - .filter(s -> s.getId().equals(sensorId) && s instanceof TemperatureSensor) + .filter(s -> s.getId().equals(sensorId) && s.getSensorType().equals(SensorType.TEMPERATURE)) .map(s -> (TemperatureSensor) s) .findFirst() .orElseThrow(() -> new SensorNotFoundException(String.format("Sensor not found with id: %s", sensorId))); From 38f15be400fc803ea607886741104ee57da2152e Mon Sep 17 00:00:00 2001 From: Selahattin <98191442+SelahattinSert@users.noreply.github.com> Date: Fri, 27 Dec 2024 21:42:33 +0300 Subject: [PATCH 30/40] Add sensor dto converter unit test --- .../converter/SensorDtoConverterTest.java | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/test/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverterTest.java diff --git a/src/test/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverterTest.java b/src/test/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverterTest.java new file mode 100644 index 0000000..7d630a9 --- /dev/null +++ b/src/test/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverterTest.java @@ -0,0 +1,70 @@ +package com.onboarding.camera.cameraonboarding.converter; + +import com.onboarding.camera.cameraonboarding.dto.SensorDto; +import com.onboarding.camera.cameraonboarding.dto.SensorResponse; +import com.onboarding.camera.cameraonboarding.entity.Sensor; +import com.onboarding.camera.cameraonboarding.entity.TemperatureSensor; +import com.onboarding.camera.cameraonboarding.enums.SensorType; +import org.assertj.core.api.AssertionsForClassTypes; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.UUID; + +class SensorDtoConverterTest { + + private SensorDtoConverter sensorDtoConverter; + + private final UUID SENSOR_ID = UUID.randomUUID(); + private final String SENSOR_NAME = "Sensor 1"; + private final String SENSOR_VERSION = "v1.0"; + private final SensorType SENSOR_TYPE = SensorType.LIGHT; + private final String SENSOR_DATA = "Sensor data"; + + @BeforeEach + void setUp() { + sensorDtoConverter = new SensorDtoConverter(); + } + + @Test + void expect_convert_withValidSensorDto_returnSensor() { + // arrange + SensorDto sensorDto = new SensorDto(); + sensorDto.setName(SENSOR_NAME); + sensorDto.setVersion(SENSOR_VERSION); + sensorDto.setSensorType(SENSOR_TYPE); + sensorDto.setData(SENSOR_DATA); + + // act + Sensor sensor = sensorDtoConverter.toLightEntity(sensorDto); + + // assert + AssertionsForClassTypes.assertThat(sensor).isNotNull(); + AssertionsForClassTypes.assertThat(sensor.getName()).isEqualTo(SENSOR_NAME); + AssertionsForClassTypes.assertThat(sensor.getVersion()).isEqualTo(SENSOR_VERSION); + AssertionsForClassTypes.assertThat(sensor.getSensorType()).isEqualTo(SENSOR_TYPE); + AssertionsForClassTypes.assertThat(sensor.getData()).isEqualTo(SENSOR_DATA); + } + + @Test + void expect_convert_withValidSensor_returnSensorDto() { + // arrange + Sensor sensor = new TemperatureSensor(); + sensor.setId(SENSOR_ID); + sensor.setName(SENSOR_NAME); + sensor.setVersion(SENSOR_VERSION); + sensor.setSensorType(SENSOR_TYPE); + sensor.setData(SENSOR_DATA); + + // act + SensorResponse response = sensorDtoConverter.toSensorResponse(sensor); + + // assert + AssertionsForClassTypes.assertThat(response).isNotNull(); + AssertionsForClassTypes.assertThat(response.getId()).isEqualTo(SENSOR_ID); + AssertionsForClassTypes.assertThat(response.getName()).isEqualTo(SENSOR_NAME); + AssertionsForClassTypes.assertThat(response.getVersion()).isEqualTo(SENSOR_VERSION); + AssertionsForClassTypes.assertThat(response.getSensorType()).isEqualTo(SENSOR_TYPE); + AssertionsForClassTypes.assertThat(response.getData()).isEqualTo(SENSOR_DATA); + } +} \ No newline at end of file From 8bff631cb995647785a416393bd7ccb84cf0c70a Mon Sep 17 00:00:00 2001 From: Selahattin <98191442+SelahattinSert@users.noreply.github.com> Date: Fri, 27 Dec 2024 21:43:59 +0300 Subject: [PATCH 31/40] Add light sensor unit and integration tests --- .../controller/LightSensorControllerTest.java | 328 ++++++++++++++++++ .../repository/LightSensorRepositoryTest.java | 215 ++++++++++++ .../service/impl/LightSensorServiceTest.java | 302 ++++++++++++++++ 3 files changed, 845 insertions(+) create mode 100644 src/test/java/com/onboarding/camera/cameraonboarding/controller/LightSensorControllerTest.java create mode 100644 src/test/java/com/onboarding/camera/cameraonboarding/repository/LightSensorRepositoryTest.java create mode 100644 src/test/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorServiceTest.java diff --git a/src/test/java/com/onboarding/camera/cameraonboarding/controller/LightSensorControllerTest.java b/src/test/java/com/onboarding/camera/cameraonboarding/controller/LightSensorControllerTest.java new file mode 100644 index 0000000..e187a04 --- /dev/null +++ b/src/test/java/com/onboarding/camera/cameraonboarding/controller/LightSensorControllerTest.java @@ -0,0 +1,328 @@ +package com.onboarding.camera.cameraonboarding.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.onboarding.camera.cameraonboarding.converter.SensorDtoConverter; +import com.onboarding.camera.cameraonboarding.dto.SensorDto; +import com.onboarding.camera.cameraonboarding.entity.Camera; +import com.onboarding.camera.cameraonboarding.entity.LightSensor; +import com.onboarding.camera.cameraonboarding.enums.SensorType; +import com.onboarding.camera.cameraonboarding.exception.SensorNotCreatedException; +import com.onboarding.camera.cameraonboarding.exception.SensorNotUpdatedException; +import com.onboarding.camera.cameraonboarding.service.impl.LightSensorService; +import org.hamcrest.CoreMatchers; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentMatchers; +import org.mockito.BDDMockito; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import java.util.Collections; +import java.util.UUID; + +@WebMvcTest(controllers = LightSensorController.class) +@AutoConfigureMockMvc(addFilters = false) +@ExtendWith(MockitoExtension.class) +@Import(SensorDtoConverter.class) +class LightSensorControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private LightSensorService lightSensorService; + + @Autowired + private ObjectMapper objectMapper; + + private SensorDto sensorDto; + + private LightSensor sensor; + + private Camera camera; + + private final UUID SENSOR_ID = UUID.randomUUID(); + private final String SENSOR_NAME = "Light Sensor 1"; + private final SensorType SENSOR_TYPE = SensorType.LIGHT; + private final String SENSOR_VERSION = "v1.0"; + private final UUID CAMERA_ID = UUID.randomUUID(); + private final String CAMERA_NAME = "Camera 1"; + private final String FIRMWARE_VERSION = "v1.0.0"; + + @BeforeEach + void setUp() { + sensorDto = new SensorDto(); + sensorDto.setName(SENSOR_NAME); + sensorDto.setSensorType(SENSOR_TYPE); + sensorDto.setVersion(SENSOR_VERSION); + sensor = new LightSensor(); + camera = new Camera(); + camera.setCamId(CAMERA_ID); + camera.setCameraName(CAMERA_NAME); + camera.setFirmwareVersion(FIRMWARE_VERSION); + } + + @Test + public void expect_handleCreateSensor_withValidSensorDto_returnCreated() throws Exception { + + // arrange + sensor.setId(SENSOR_ID); + sensor.setName(SENSOR_NAME); + sensor.setSensorType(SENSOR_TYPE); + BDDMockito.given(lightSensorService.handleCreateSensor(Mockito.eq(CAMERA_ID), ArgumentMatchers.any(LightSensor.class))).willReturn(sensor); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/camera/{cameraId}/sensor/light", CAMERA_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isCreated()) + .andExpect(MockMvcResultMatchers.jsonPath("$.id", CoreMatchers.is(SENSOR_ID.toString()))) + .andExpect(MockMvcResultMatchers.jsonPath("$.name", CoreMatchers.is(SENSOR_NAME))) + .andExpect(MockMvcResultMatchers.jsonPath("$.sensorType", CoreMatchers.is(SENSOR_TYPE.toString()))); + + Mockito.verify(lightSensorService).handleCreateSensor(Mockito.eq(CAMERA_ID), ArgumentMatchers.any(LightSensor.class)); + } + + @Test + public void expect_handleCreateSensor_withNullSensorName_returnBadRequest() throws Exception { + + // arrange + sensorDto.setName(null); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/camera/{cameraId}/sensor/light", CAMERA_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isBadRequest()); + + Mockito.verify(lightSensorService, Mockito.never()).handleCreateSensor(Mockito.eq(CAMERA_ID), ArgumentMatchers.any(LightSensor.class)); + } + + @Test + public void expect_handleCreateSensor_withNullSensorType_returnBadRequest() throws Exception { + + // arrange + sensorDto.setSensorType(null); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/camera/{cameraId}/sensor/light", CAMERA_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isBadRequest()); + + Mockito.verify(lightSensorService, Mockito.never()).handleCreateSensor(Mockito.eq(CAMERA_ID), ArgumentMatchers.any(LightSensor.class)); + } + + @Test + void expect_handleCreateLightSensor_withSensorNotCreatedException_returnInternalServerError() throws Exception { + + // arrange + Mockito.doThrow(new SensorNotCreatedException("Failed to create sensor")) + .when(lightSensorService).handleCreateSensor(ArgumentMatchers.eq(CAMERA_ID), ArgumentMatchers.any(LightSensor.class)); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/camera/{cameraId}/sensor/light", CAMERA_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isInternalServerError()); + + Mockito.verify(lightSensorService).handleCreateSensor(ArgumentMatchers.eq(CAMERA_ID), ArgumentMatchers.any(LightSensor.class)); + } + + @Test + void expect_getLightSensors_withValidCameraId_returnOk() throws Exception { + + // arrange + sensor.setId(SENSOR_ID); + sensor.setName(SENSOR_NAME); + sensor.setSensorType(SENSOR_TYPE); + BDDMockito.given(lightSensorService.handleGetSensorsByCameraId(CAMERA_ID)) + .willReturn(Collections.singletonList(sensor)); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/camera/{cameraId}/sensor/light", CAMERA_ID) + .contentType(MediaType.APPLICATION_JSON)); + + // assert + response.andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].id", CoreMatchers.is(SENSOR_ID.toString()))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].name", CoreMatchers.is(SENSOR_NAME))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sensorType", CoreMatchers.is(SENSOR_TYPE.toString()))); + + Mockito.verify(lightSensorService).handleGetSensorsByCameraId(CAMERA_ID); + } + + @Test + void expect_getLightSensors_withNullCameraId_returnNotFound() throws Exception { + + // arrange + camera.setCamId(null); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/camera/{cameraId}/sensor/light", camera.getCamId()) + .contentType(MediaType.APPLICATION_JSON)); + + // assert + response.andExpect(MockMvcResultMatchers.status().isNotFound()); + } + + @Test + void expect_handleUpdateLightSensor_withValidRequest_returnOk() throws Exception { + + // arrange + sensor.setId(SENSOR_ID); + String updatedName = "Updated Name"; + sensor.setName(updatedName); + sensor.setSensorType(SENSOR_TYPE); + BDDMockito.given(lightSensorService.handleUpdateSensor(Mockito.eq(CAMERA_ID), Mockito.eq(SENSOR_ID), ArgumentMatchers.any(LightSensor.class))) + .willReturn(sensor); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.put("/api/v1/camera/{cameraId}/sensor/light/{sensorId}", CAMERA_ID, SENSOR_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.id", CoreMatchers.is(SENSOR_ID.toString()))) + .andExpect(MockMvcResultMatchers.jsonPath("$.name", CoreMatchers.is(updatedName))) + .andExpect(MockMvcResultMatchers.jsonPath("$.sensorType", CoreMatchers.is(SENSOR_TYPE.toString()))); + + Mockito.verify(lightSensorService).handleUpdateSensor(Mockito.eq(CAMERA_ID), Mockito.eq(SENSOR_ID), ArgumentMatchers.any(LightSensor.class)); + } + + @Test + void expect_handleUpdateLightSensor_withNullSensorId_returnNotFound() throws Exception { + + // arrange + sensor.setId(null); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.put("/api/v1/camera/{cameraId}/sensor/light/{sensorId}", CAMERA_ID, sensor.getId()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isNotFound()); + + Mockito.verify(lightSensorService, Mockito.never()).handleUpdateSensor(Mockito.eq(CAMERA_ID), Mockito.eq(sensor.getId()), ArgumentMatchers.any(LightSensor.class)); + } + + @Test + void expect_handleUpdateLightSensor_withNullCameraId_returnNotFound() throws Exception { + + // arrange + camera.setCamId(null); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.put("/api/v1/camera/{cameraId}/sensor/light/{sensorId}", camera.getCamId(), SENSOR_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isNotFound()); + + Mockito.verify(lightSensorService, Mockito.never()).handleUpdateSensor(Mockito.eq(camera.getCamId()), Mockito.eq(SENSOR_ID), ArgumentMatchers.any(LightSensor.class)); + } + + @Test + void expect_handleUpdateLightSensor_withSensorNotUpdatedException_returnInternalServerError() throws Exception { + + // arrange + Mockito.doThrow(new SensorNotUpdatedException("Error occurred while deleting sensor")) + .when(lightSensorService).handleUpdateSensor(ArgumentMatchers.eq(CAMERA_ID), ArgumentMatchers.eq(SENSOR_ID), ArgumentMatchers.any(LightSensor.class)); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.put("/api/v1/camera/{cameraId}/sensor/light/{sensorId}", CAMERA_ID, SENSOR_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isInternalServerError()); + + Mockito.verify(lightSensorService).handleUpdateSensor(ArgumentMatchers.eq(CAMERA_ID), ArgumentMatchers.eq(SENSOR_ID), ArgumentMatchers.any(LightSensor.class)); + } + + @Test + void expect_handleDeleteLightSensor_withValidRequest_returnNoContent() throws Exception { + // Act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.delete("/api/v1/camera/{cameraId}/sensor/light/{sensorId}", CAMERA_ID, SENSOR_ID) + .contentType(MediaType.APPLICATION_JSON)); + + // Assert + response.andExpect(MockMvcResultMatchers.status().isNoContent()); + + Mockito.verify(lightSensorService).handleDeleteSensor(CAMERA_ID, SENSOR_ID); + } + + @Test + void expect_handleDeleteLightSensor_withNullSensorId_returnNotFound() throws Exception { + + // arrange + sensor.setId(null); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.delete("/api/v1/camera/{cameraId}/sensor/light/{sensorId}", CAMERA_ID, sensor.getId()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isNotFound()); + + Mockito.verify(lightSensorService, Mockito.never()).handleDeleteSensor(Mockito.eq(CAMERA_ID), Mockito.eq(sensor.getId())); + } + + @Test + void expect_handleDeleteLightSensor_withNullCameraId_returnNotFound() throws Exception { + + // arrange + camera.setCamId(null); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.delete("/api/v1/camera/{cameraId}/sensor/light/{sensorId}", camera.getCamId(), SENSOR_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isNotFound()); + + Mockito.verify(lightSensorService, Mockito.never()).handleDeleteSensor(Mockito.eq(camera.getCamId()), Mockito.eq(SENSOR_ID)); + } + + @Test + void expect_handleDeleteLightSensor_withSensorNotUpdatedException_returnInternalServerError() throws Exception { + + // arrange + Mockito.doThrow(new SensorNotUpdatedException("Error occurred while deleting sensor")) + .when(lightSensorService).handleDeleteSensor(CAMERA_ID, SENSOR_ID); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.delete("/api/v1/camera/{cameraId}/sensor/light/{sensorId}", camera.getCamId(), SENSOR_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isInternalServerError()); + + Mockito.verify(lightSensorService).handleDeleteSensor(ArgumentMatchers.eq(CAMERA_ID), ArgumentMatchers.eq(SENSOR_ID)); + } +} \ No newline at end of file diff --git a/src/test/java/com/onboarding/camera/cameraonboarding/repository/LightSensorRepositoryTest.java b/src/test/java/com/onboarding/camera/cameraonboarding/repository/LightSensorRepositoryTest.java new file mode 100644 index 0000000..da089b2 --- /dev/null +++ b/src/test/java/com/onboarding/camera/cameraonboarding/repository/LightSensorRepositoryTest.java @@ -0,0 +1,215 @@ +package com.onboarding.camera.cameraonboarding.repository; + +import com.onboarding.camera.cameraonboarding.entity.Camera; +import com.onboarding.camera.cameraonboarding.entity.LightSensor; +import com.onboarding.camera.cameraonboarding.entity.Sensor; +import com.onboarding.camera.cameraonboarding.enums.SensorType; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +@DataJpaTest +class LightSensorRepositoryTest { + + @Autowired + LightSensorRepository lightSensorRepository; + + @Autowired + CameraRepository cameraRepository; + + private LightSensor lightSensor; + + private final String SENSOR_NAME = "Light Sensor 1"; + private final String SENSOR_NAME_2 = "Light Sensor 2"; + private final SensorType SENSOR_TYPE = SensorType.LIGHT; + private final UUID NON_EXISTING_UUID = UUID.fromString("ef556dc0-0ddc-4f39-a96d-6886a54eee54"); + private final UUID CAMERA_ID = UUID.randomUUID(); + private final String CAMERA_NAME = "Camera 1"; + private final String FIRMWARE_VERSION = "v1.0"; + + @BeforeEach + void setUp() { + lightSensor = new LightSensor(); + lightSensor.setName(SENSOR_NAME); + lightSensor.setSensorType(SENSOR_TYPE); + } + + @Test + @Transactional + public void expect_save_sensorRepository_saveAll_returnsSavedSensor() { + + // act + Sensor savedSensor = lightSensorRepository.save(lightSensor); + + // assert + Assertions.assertThat(savedSensor).isNotNull(); + Assertions.assertThat(savedSensor.getName()).isNotNull(); + Assertions.assertThat(savedSensor.getName()).isEqualTo(SENSOR_NAME); + Assertions.assertThat(savedSensor.getSensorType()).isNotNull(); + Assertions.assertThat(savedSensor.getSensorType()).isEqualTo(SENSOR_TYPE); + Assertions.assertThat(savedSensor.getId()).isNotNull(); + } + + @Test + @Transactional + public void expect_save_sensorWithNullName_throwsException() { + + // arrange + lightSensor.setName(null); + + // act and assert + Assertions.assertThatThrownBy(() -> + lightSensorRepository.saveAndFlush(lightSensor) + ).isInstanceOf(DataIntegrityViolationException.class); + } + + @Test + @Transactional + public void expect_save_sensorWithNullType_throwsException() { + + // arrange + lightSensor.setSensorType(null); + + // act and assert + Assertions.assertThatThrownBy(() -> + lightSensorRepository.saveAndFlush(lightSensor) + ).isInstanceOf(DataIntegrityViolationException.class); + } + + @Test + public void expect_findById_lightSensorRepository_returnsSensor() { + + // arrange + lightSensorRepository.save(lightSensor); + + // act + Optional foundSensor = lightSensorRepository.findById(lightSensor.getId()); + + //assert + Assertions.assertThat(foundSensor).isPresent(); + Assertions.assertThat(foundSensor.get().getId()).isEqualTo(lightSensor.getId()); + } + + @Test + public void expect_findById_sensorWithNotExistingId_throwsException() { + + // act + Optional foundSensor = lightSensorRepository.findById(NON_EXISTING_UUID); + + // assert + Assertions.assertThat(foundSensor).isEmpty(); + } + + @Test + public void expect_delete_sensorWithExistingId_returnsVoid() { + + // Arrange + LightSensor savedSensor = lightSensorRepository.save(lightSensor); + Camera associatedCamera = new Camera(); + associatedCamera.setCamId(CAMERA_ID); + associatedCamera.setCameraName(CAMERA_NAME); + associatedCamera.setFirmwareVersion(FIRMWARE_VERSION); + savedSensor.setCamera(associatedCamera); + lightSensorRepository.save(savedSensor); + + // Act + lightSensorRepository.delete(savedSensor); + + // Assert + Optional foundSensor = lightSensorRepository.findById(savedSensor.getId()); + Assertions.assertThat(foundSensor).isEmpty(); + } + + @Test + @Transactional + public void expect_deleteCamera_removesAssociatedSensors() { + // Arrange + Camera camera = new Camera(); + camera.setCamId(CAMERA_ID); + camera.setCameraName(CAMERA_NAME); + camera.setFirmwareVersion(FIRMWARE_VERSION); + camera = cameraRepository.save(camera); + + LightSensor sensor1 = new LightSensor(); + sensor1.setName(SENSOR_NAME); + sensor1.setSensorType(SENSOR_TYPE); + sensor1.setCamera(camera); + + LightSensor sensor2 = new LightSensor(); + sensor2.setName(SENSOR_NAME_2); + sensor2.setSensorType(SENSOR_TYPE); + sensor2.setCamera(camera); + + lightSensorRepository.save(sensor1); + lightSensorRepository.save(sensor2); + + // Act + lightSensorRepository.deleteAll(); + cameraRepository.delete(camera); + + // Assert + Assertions.assertThat(lightSensorRepository.findLightSensorByCamera(camera)).isEmpty(); + } + + @Test + @Transactional + public void expect_findLightSensorsByCamera_returnsLightSensors() { + // Arrange + Camera camera = new Camera(); + camera.setCamId(CAMERA_ID); + camera.setCameraName(CAMERA_NAME); + camera.setFirmwareVersion(FIRMWARE_VERSION); + Camera savedCamera = cameraRepository.save(camera); + + LightSensor sensor1 = new LightSensor(); + sensor1.setName(SENSOR_NAME); + sensor1.setSensorType(SENSOR_TYPE); + sensor1.setCamera(savedCamera); + + LightSensor sensor2 = new LightSensor(); + sensor2.setName(SENSOR_NAME_2); + sensor2.setSensorType(SENSOR_TYPE); + sensor2.setCamera(savedCamera); + + lightSensorRepository.save(sensor1); + lightSensorRepository.save(sensor2); + + // Act + List sensors = lightSensorRepository.findLightSensorByCamera(savedCamera); + + // Assert + Assertions.assertThat(sensors).hasSize(2); + Assertions.assertThat(sensors).extracting(LightSensor::getName) + .containsExactlyInAnyOrder("Light Sensor 1", "Light Sensor 2"); + } + + @Test + @Transactional + public void expect_updateSensor_withValidSensor_returnsUpdatedSensor() { + // Arrange + LightSensor savedSensor = lightSensorRepository.save(lightSensor); + String updatedName = "Updated Sensor Name"; + String updatedSensorVersion = "v1.1"; + String updatedSensorData = "Sensor Data"; + + // Act + savedSensor.setName(updatedName); + savedSensor.setVersion(updatedSensorVersion); + savedSensor.setData(updatedSensorData); + LightSensor updatedSensor = lightSensorRepository.save(savedSensor); + + // Assert + Assertions.assertThat(updatedSensor).isNotNull(); + Assertions.assertThat(updatedSensor.getName()).isEqualTo(updatedName); + Assertions.assertThat(updatedSensor.getVersion()).isEqualTo(updatedSensorVersion); + Assertions.assertThat(updatedSensor.getData()).isEqualTo(updatedSensorData); + } +} \ No newline at end of file diff --git a/src/test/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorServiceTest.java b/src/test/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorServiceTest.java new file mode 100644 index 0000000..13b778c --- /dev/null +++ b/src/test/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorServiceTest.java @@ -0,0 +1,302 @@ +package com.onboarding.camera.cameraonboarding.service.impl; + +import com.onboarding.camera.cameraonboarding.entity.Camera; +import com.onboarding.camera.cameraonboarding.entity.LightSensor; +import com.onboarding.camera.cameraonboarding.enums.SensorType; +import com.onboarding.camera.cameraonboarding.exception.CameraNotFoundException; +import com.onboarding.camera.cameraonboarding.exception.SensorNotCreatedException; +import com.onboarding.camera.cameraonboarding.exception.SensorNotFoundException; +import com.onboarding.camera.cameraonboarding.exception.SensorNotUpdatedException; +import com.onboarding.camera.cameraonboarding.repository.LightSensorRepository; +import com.onboarding.camera.cameraonboarding.service.CameraService; +import jakarta.transaction.Transactional; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@ExtendWith(MockitoExtension.class) +class LightSensorServiceTest { + + @Mock + private LightSensorRepository lightSensorRepository; + + @Mock + private CameraService cameraService; + + @Mock + private Camera camera; + + @InjectMocks + private LightSensorService lightSensorService; + + private LightSensor sensor; + + + private final UUID SENSOR_ID = UUID.randomUUID(); + private final String SENSOR_NAME = "Light Sensor 1"; + private final SensorType SENSOR_TYPE = SensorType.LIGHT; + private final UUID CAMERA_ID = UUID.randomUUID(); + private final UUID NON_EXISTING_CAM_ID = UUID.fromString("ef556dc0-0ddc-4f39-a96d-6886a54eee54"); + + @BeforeEach + void setUp() { + sensor = new LightSensor(); + sensor.setId(SENSOR_ID); + sensor.setName(SENSOR_NAME); + sensor.setSensorType(SENSOR_TYPE); + } + + @Test + @Transactional + void expect_handleCreateSensor_withValidSensor_returnSavedSensor() { + + // arrange + Mockito.when(lightSensorRepository.save(sensor)).thenReturn(sensor); + + // act + LightSensor savedSensor = lightSensorService.handleCreateSensor(CAMERA_ID, sensor); + + // assert + Assertions.assertThat(savedSensor) + .isNotNull() + .satisfies(sensor -> { + Assertions.assertThat(sensor.getName()) + .as("Check Sensor Name") + .isNotNull() + .isEqualTo(SENSOR_NAME); + + Assertions.assertThat(sensor.getSensorType()) + .as("Check Sensor Type") + .isNotNull() + .isEqualTo(SENSOR_TYPE); + }); + + Mockito.verify(lightSensorRepository).save(sensor); + } + + @Test + void expect_handleCreateSensor_withNonExistingCamera_throwsCameraNotFoundException() { + + // arrange + camera.setCamId(NON_EXISTING_CAM_ID); + Mockito.when(lightSensorRepository.save(sensor)).thenThrow(new CameraNotFoundException("Camera not found, cameraId:" + NON_EXISTING_CAM_ID)); + + // act and assert + Assertions.assertThatThrownBy(() -> lightSensorService.handleCreateSensor(NON_EXISTING_CAM_ID, sensor)) + .isInstanceOf(CameraNotFoundException.class); + + Mockito.verify(lightSensorRepository).save(sensor); + } + + @Test + void expect_handleCreateSensor_withNullSensorName_throwsException() { + + // arrange + sensor.setName(null); + Mockito.when(lightSensorRepository.save(sensor)).thenThrow(new SensorNotCreatedException("Sensor name cannot be null")); + + // act and assert + Assertions.assertThatThrownBy(() -> lightSensorService.handleCreateSensor(CAMERA_ID, sensor)) + .isInstanceOf(SensorNotCreatedException.class); + + Mockito.verify(lightSensorRepository).save(sensor); + } + + @Test + void expect_handleCreateSensor_withNullSensorType_throwsException() { + + // arrange + sensor.setSensorType(null); + Mockito.when(lightSensorRepository.save(sensor)).thenThrow(new SensorNotCreatedException("Sensor type cannot be null")); + + // act and assert + Assertions.assertThatThrownBy(() -> lightSensorService.handleCreateSensor(CAMERA_ID, sensor)) + .isInstanceOf(SensorNotCreatedException.class); + + Mockito.verify(lightSensorRepository).save(sensor); + } + + @Test + void expect_handleUpdateSensor_withValidData_returnsUpdatedSensor() { + // arrange + sensor.setCamera(camera); + sensor.setName("Updated Name"); + sensor.setVersion("v1.1"); + sensor.setData("Updated Data"); + Mockito.when(cameraService.getCameraById(CAMERA_ID)).thenReturn(camera); + Mockito.when(lightSensorRepository.save(sensor)).thenReturn(sensor); + Mockito.when(camera.getSensors()).thenReturn(new ArrayList<>(List.of(sensor))); + + // act + LightSensor updatedSensor = lightSensorService.handleUpdateSensor(CAMERA_ID, SENSOR_ID, sensor); + + // assert + Assertions.assertThat(updatedSensor) + .isNotNull() + .satisfies(sensor -> { + Assertions.assertThat(sensor.getName()) + .as("Check Sensor Name") + .isNotNull() + .isEqualTo("Updated Name"); + + Assertions.assertThat(sensor.getVersion()) + .as("Check Sensor Version") + .isNotNull() + .isEqualTo("v1.1"); + + Assertions.assertThat(sensor.getCamera()) + .as("Check Sensor Camera") + .isNotNull() + .isEqualTo(camera); + + Assertions.assertThat(sensor.getData()) + .as("Check Sensor Data") + .isNotNull() + .isEqualTo("Updated Data"); + }); + + Mockito.verify(lightSensorRepository).save(sensor); + } + + @Test + void expect_handleUpdateSensor_withNonExistingSensor_throwsSensorNotFoundException() { + + // arrange + Mockito.when(cameraService.getCameraById(CAMERA_ID)).thenReturn(camera); + Mockito.when(camera.getSensors()).thenReturn(List.of()); + + // act and assert + Assertions.assertThatThrownBy(() -> lightSensorService.handleUpdateSensor(CAMERA_ID, SENSOR_ID, sensor)) + .isInstanceOf(SensorNotFoundException.class) + .hasMessageContaining("Sensor not found"); + + Mockito.verify(lightSensorRepository, Mockito.never()).save(Mockito.any()); + } + + @Test + void expect_handleUpdateSensor_withNonExistingCamera_throwsCameraNotFoundException() { + // arrange + Mockito.when(cameraService.getCameraById(CAMERA_ID)).thenThrow(new CameraNotFoundException("Camera not found, cameraId:" + CAMERA_ID)); + + // act and assert + Assertions.assertThatThrownBy(() -> lightSensorService.handleUpdateSensor(CAMERA_ID, SENSOR_ID, sensor)) + .isInstanceOf(CameraNotFoundException.class) + .hasMessageContaining("Camera not found"); + + Mockito.verify(lightSensorRepository, Mockito.never()).save(Mockito.any()); + } + + @Test + void expect_handleUpdateSensor_withRepositoryError_throwsSensorNotUpdatedException() { + + // arrange + Mockito.when(cameraService.getCameraById(CAMERA_ID)).thenReturn(camera); + Mockito.when(camera.getSensors()).thenReturn(new ArrayList<>(List.of(sensor))); + Mockito.when(lightSensorRepository.save(sensor)) + .thenThrow(new SensorNotUpdatedException("Error occurred while updating sensors")); + + // act and assert + Assertions.assertThatThrownBy(() -> lightSensorService.handleUpdateSensor(CAMERA_ID, SENSOR_ID, sensor)) + .isInstanceOf(SensorNotUpdatedException.class) + .hasMessageContaining("Error occurred while updating sensors"); + + Mockito.verify(lightSensorRepository).save(sensor); + } + + @Test + void expect_getSensorById_withValidSensorId_returnsSensor() { + + // arrange + Mockito.when(lightSensorRepository.findById(SENSOR_ID)).thenReturn(java.util.Optional.of(sensor)); + + // act + LightSensor foundSensor = lightSensorService.getSensorById(SENSOR_ID); + + // assert + Assertions.assertThat(foundSensor).isEqualTo(sensor); + Mockito.verify(lightSensorRepository).findById(SENSOR_ID); + } + + @Test + void expect_getSensorById_withInvalidSensorId_throwsSensorNotFoundException() { + + // arrange + Mockito.when(lightSensorRepository.findById(SENSOR_ID)).thenReturn(java.util.Optional.empty()); + + // act and assert + Assertions.assertThatThrownBy(() -> lightSensorService.getSensorById(SENSOR_ID)) + .isInstanceOf(SensorNotFoundException.class); + + Mockito.verify(lightSensorRepository).findById(SENSOR_ID); + } + + @Test + void expect_handleDeleteSensor_withValidData_deletesSensor() { + + // arrange + Mockito.when(cameraService.getCameraById(CAMERA_ID)).thenReturn(camera); + Mockito.when(camera.getSensors()).thenReturn(new ArrayList<>(List.of(sensor))); + + // act + lightSensorService.handleDeleteSensor(CAMERA_ID, SENSOR_ID); + + // assert + Mockito.verify(lightSensorRepository).delete(sensor); + } + + @Test + void expect_handleDeleteSensor_withNonExistingSensor_throwsSensorNotFoundException() { + + // arrange + Mockito.when(cameraService.getCameraById(CAMERA_ID)).thenReturn(camera); + Mockito.when(camera.getSensors()).thenReturn(List.of()); + + // act and assert + Assertions.assertThatThrownBy(() -> lightSensorService.handleDeleteSensor(CAMERA_ID, SENSOR_ID)) + .isInstanceOf(SensorNotFoundException.class) + .hasMessageContaining("Sensor not found with id"); + + Mockito.verify(lightSensorRepository, Mockito.never()).delete(Mockito.any()); + } + + @Test + void expect_handleDeleteSensor_withNonExistingCamera_throwsCameraNotFoundException() { + + // arrange + Mockito.when(cameraService.getCameraById(CAMERA_ID)) + .thenThrow(new CameraNotFoundException("Camera not found, cameraId:" + CAMERA_ID)); + + // act and assert + Assertions.assertThatThrownBy(() -> lightSensorService.handleDeleteSensor(CAMERA_ID, SENSOR_ID)) + .isInstanceOf(CameraNotFoundException.class) + .hasMessageContaining("Camera not found, cameraId"); + + Mockito.verify(lightSensorRepository, Mockito.never()).delete(Mockito.any()); + } + + @Test + void expect_handleDeleteSensor_withRepositoryError_throwsSensorNotUpdatedException() { + + // arrange + Mockito.when(cameraService.getCameraById(CAMERA_ID)).thenReturn(camera); + Mockito.when(camera.getSensors()).thenReturn(new ArrayList<>(List.of(sensor))); + Mockito.doThrow(new RuntimeException("Error occurred while deleting sensor")) + .when(lightSensorRepository).delete(sensor); + + // act and assert + Assertions.assertThatThrownBy(() -> lightSensorService.handleDeleteSensor(CAMERA_ID, SENSOR_ID)) + .isInstanceOf(SensorNotUpdatedException.class) + .hasMessageContaining("Error occurred while deleting sensor"); + + Mockito.verify(lightSensorRepository).delete(sensor); + } +} \ No newline at end of file From 33d39d6627812838363ae194de8de3496e834d18 Mon Sep 17 00:00:00 2001 From: Selahattin <98191442+SelahattinSert@users.noreply.github.com> Date: Sun, 29 Dec 2024 20:05:28 +0300 Subject: [PATCH 32/40] Add sensor dto validation method --- .../converter/SensorDtoConverter.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/main/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverter.java b/src/main/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverter.java index 039c6f9..db75c9d 100644 --- a/src/main/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverter.java +++ b/src/main/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverter.java @@ -8,12 +8,15 @@ import com.onboarding.camera.cameraonboarding.entity.TemperatureSensor; import com.onboarding.camera.cameraonboarding.enums.SensorType; import com.onboarding.camera.cameraonboarding.exception.SensorMismatchException; +import com.onboarding.camera.cameraonboarding.exception.SensorNotCreatedException; import org.springframework.stereotype.Component; @Component public class SensorDtoConverter { public MotionSensor toMotionEntity(SensorDto sensorDto) { + + validateSensorDto(sensorDto); if (sensorDto.getSensorType() != SensorType.MOTION) { throw new SensorMismatchException("Invalid sensor type for MotionSensor"); } @@ -27,6 +30,8 @@ public MotionSensor toMotionEntity(SensorDto sensorDto) { } public LightSensor toLightEntity(SensorDto sensorDto) { + + validateSensorDto(sensorDto); if (sensorDto.getSensorType() != SensorType.LIGHT) { throw new SensorMismatchException("Invalid sensor type for LightSensor"); } @@ -40,6 +45,8 @@ public LightSensor toLightEntity(SensorDto sensorDto) { } public TemperatureSensor toTemperatureEntity(SensorDto sensorDto) { + + validateSensorDto(sensorDto); if (sensorDto.getSensorType() != SensorType.TEMPERATURE) { throw new SensorMismatchException("Invalid sensor type for TemperatureSensor"); } @@ -61,4 +68,22 @@ public SensorResponse toSensorResponse(Sensor sensor) { response.setData(sensor.getData()); return response; } + + /** + * Validates if the camera has been onboarded and initialized + * + * @param sensorDto the sensor dto to check + * @throws SensorNotCreatedException if the sensor name, version or type is null + */ + private void validateSensorDto(SensorDto sensorDto) { + if (sensorDto.getName() == null || sensorDto.getName().isBlank()) { + throw new SensorNotCreatedException("Sensor name cannot be null"); + } + if (sensorDto.getVersion() == null || sensorDto.getVersion().isBlank()) { + throw new SensorNotCreatedException("Sensor version cannot be null"); + } + if (sensorDto.getSensorType() == null || sensorDto.getSensorType().toString().isBlank()) { + throw new SensorNotCreatedException("Sensor type cannot be null"); + } + } } From 402a178697feaa2b9ec416a488ca18c9c45ccd94 Mon Sep 17 00:00:00 2001 From: Selahattin <98191442+SelahattinSert@users.noreply.github.com> Date: Sun, 29 Dec 2024 20:06:07 +0300 Subject: [PATCH 33/40] Add test cases for invalid data --- .../converter/SensorDtoConverterTest.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/test/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverterTest.java b/src/test/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverterTest.java index 7d630a9..5570135 100644 --- a/src/test/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverterTest.java +++ b/src/test/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverterTest.java @@ -5,6 +5,8 @@ import com.onboarding.camera.cameraonboarding.entity.Sensor; import com.onboarding.camera.cameraonboarding.entity.TemperatureSensor; import com.onboarding.camera.cameraonboarding.enums.SensorType; +import com.onboarding.camera.cameraonboarding.exception.SensorNotCreatedException; +import org.assertj.core.api.Assertions; import org.assertj.core.api.AssertionsForClassTypes; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -67,4 +69,46 @@ void expect_convert_withValidSensor_returnSensorDto() { AssertionsForClassTypes.assertThat(response.getSensorType()).isEqualTo(SENSOR_TYPE); AssertionsForClassTypes.assertThat(response.getData()).isEqualTo(SENSOR_DATA); } + + @Test + void expect_convert_withNullSensorName_throwsException() { + // arrange + SensorDto sensorDto = new SensorDto(); + sensorDto.setName(null); + + + // act and assert + Assertions.assertThatThrownBy(() -> sensorDtoConverter.toLightEntity(sensorDto)) + .isInstanceOf(SensorNotCreatedException.class) + .hasMessage("Sensor name cannot be null"); + } + + @Test + void expect_convert_withNullSensorVersion_throwsException() { + // arrange + SensorDto sensorDto = new SensorDto(); + sensorDto.setName(SENSOR_NAME); + sensorDto.setVersion(null); + + + // act and assert + Assertions.assertThatThrownBy(() -> sensorDtoConverter.toLightEntity(sensorDto)) + .isInstanceOf(SensorNotCreatedException.class) + .hasMessage("Sensor version cannot be null"); + } + + @Test + void expect_convert_withNullSensorType_throwsException() { + // arrange + SensorDto sensorDto = new SensorDto(); + sensorDto.setName(SENSOR_NAME); + sensorDto.setVersion(SENSOR_VERSION); + sensorDto.setSensorType(null); + + + // act and assert + Assertions.assertThatThrownBy(() -> sensorDtoConverter.toLightEntity(sensorDto)) + .isInstanceOf(SensorNotCreatedException.class) + .hasMessage("Sensor type cannot be null"); + } } \ No newline at end of file From 914a5c1062e80235f01923d92c3e29ea233525de Mon Sep 17 00:00:00 2001 From: Selahattin <98191442+SelahattinSert@users.noreply.github.com> Date: Sun, 29 Dec 2024 20:07:03 +0300 Subject: [PATCH 34/40] Fix sensor test methods --- .../controller/LightSensorControllerTest.java | 6 +- .../repository/LightSensorRepositoryTest.java | 4 +- .../service/impl/LightSensorServiceTest.java | 92 +++++-------------- 3 files changed, 28 insertions(+), 74 deletions(-) diff --git a/src/test/java/com/onboarding/camera/cameraonboarding/controller/LightSensorControllerTest.java b/src/test/java/com/onboarding/camera/cameraonboarding/controller/LightSensorControllerTest.java index e187a04..4d3a6cd 100644 --- a/src/test/java/com/onboarding/camera/cameraonboarding/controller/LightSensorControllerTest.java +++ b/src/test/java/com/onboarding/camera/cameraonboarding/controller/LightSensorControllerTest.java @@ -80,7 +80,7 @@ public void expect_handleCreateSensor_withValidSensorDto_returnCreated() throws sensor.setId(SENSOR_ID); sensor.setName(SENSOR_NAME); sensor.setSensorType(SENSOR_TYPE); - BDDMockito.given(lightSensorService.handleCreateSensor(Mockito.eq(CAMERA_ID), ArgumentMatchers.any(LightSensor.class))).willReturn(sensor); + Mockito.when(lightSensorService.handleCreateSensor(Mockito.eq(CAMERA_ID), ArgumentMatchers.any(LightSensor.class))).thenReturn(sensor); // act ResultActions response = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/camera/{cameraId}/sensor/light", CAMERA_ID) @@ -193,8 +193,8 @@ void expect_handleUpdateLightSensor_withValidRequest_returnOk() throws Exception String updatedName = "Updated Name"; sensor.setName(updatedName); sensor.setSensorType(SENSOR_TYPE); - BDDMockito.given(lightSensorService.handleUpdateSensor(Mockito.eq(CAMERA_ID), Mockito.eq(SENSOR_ID), ArgumentMatchers.any(LightSensor.class))) - .willReturn(sensor); + Mockito.when(lightSensorService.handleUpdateSensor(Mockito.eq(CAMERA_ID), Mockito.eq(SENSOR_ID), ArgumentMatchers.any(LightSensor.class))) + .thenReturn(sensor); // act ResultActions response = mockMvc.perform(MockMvcRequestBuilders.put("/api/v1/camera/{cameraId}/sensor/light/{sensorId}", CAMERA_ID, SENSOR_ID) diff --git a/src/test/java/com/onboarding/camera/cameraonboarding/repository/LightSensorRepositoryTest.java b/src/test/java/com/onboarding/camera/cameraonboarding/repository/LightSensorRepositoryTest.java index da089b2..fb8db07 100644 --- a/src/test/java/com/onboarding/camera/cameraonboarding/repository/LightSensorRepositoryTest.java +++ b/src/test/java/com/onboarding/camera/cameraonboarding/repository/LightSensorRepositoryTest.java @@ -59,7 +59,6 @@ public void expect_save_sensorRepository_saveAll_returnsSavedSensor() { } @Test - @Transactional public void expect_save_sensorWithNullName_throwsException() { // arrange @@ -72,7 +71,6 @@ public void expect_save_sensorWithNullName_throwsException() { } @Test - @Transactional public void expect_save_sensorWithNullType_throwsException() { // arrange @@ -188,7 +186,7 @@ public void expect_findLightSensorsByCamera_returnsLightSensors() { // Assert Assertions.assertThat(sensors).hasSize(2); Assertions.assertThat(sensors).extracting(LightSensor::getName) - .containsExactlyInAnyOrder("Light Sensor 1", "Light Sensor 2"); + .containsExactlyInAnyOrder(SENSOR_NAME, SENSOR_NAME_2); } @Test diff --git a/src/test/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorServiceTest.java b/src/test/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorServiceTest.java index 13b778c..aa47bac 100644 --- a/src/test/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorServiceTest.java +++ b/src/test/java/com/onboarding/camera/cameraonboarding/service/impl/LightSensorServiceTest.java @@ -4,7 +4,6 @@ import com.onboarding.camera.cameraonboarding.entity.LightSensor; import com.onboarding.camera.cameraonboarding.enums.SensorType; import com.onboarding.camera.cameraonboarding.exception.CameraNotFoundException; -import com.onboarding.camera.cameraonboarding.exception.SensorNotCreatedException; import com.onboarding.camera.cameraonboarding.exception.SensorNotFoundException; import com.onboarding.camera.cameraonboarding.exception.SensorNotUpdatedException; import com.onboarding.camera.cameraonboarding.repository.LightSensorRepository; @@ -46,6 +45,9 @@ class LightSensorServiceTest { private final SensorType SENSOR_TYPE = SensorType.LIGHT; private final UUID CAMERA_ID = UUID.randomUUID(); private final UUID NON_EXISTING_CAM_ID = UUID.fromString("ef556dc0-0ddc-4f39-a96d-6886a54eee54"); + private final String UPDATED_SENSOR_NAME = "Updated Light Sensor"; + private final String SENSOR_VERSION = "V1.0"; + private final String UPDATED_SENSOR_DATA = "Updated Sensor Data"; @BeforeEach void setUp() { @@ -66,19 +68,14 @@ void expect_handleCreateSensor_withValidSensor_returnSavedSensor() { LightSensor savedSensor = lightSensorService.handleCreateSensor(CAMERA_ID, sensor); // assert - Assertions.assertThat(savedSensor) - .isNotNull() - .satisfies(sensor -> { - Assertions.assertThat(sensor.getName()) - .as("Check Sensor Name") - .isNotNull() - .isEqualTo(SENSOR_NAME); - - Assertions.assertThat(sensor.getSensorType()) - .as("Check Sensor Type") - .isNotNull() - .isEqualTo(SENSOR_TYPE); - }); + Assertions.assertThat(savedSensor).isNotNull(); + Assertions.assertThat(savedSensor).isEqualTo(sensor); + Assertions.assertThat(savedSensor.getId()).isNotNull(); + Assertions.assertThat(savedSensor.getId()).isEqualTo(SENSOR_ID); + Assertions.assertThat(savedSensor.getName()).isNotNull(); + Assertions.assertThat(savedSensor.getName()).isEqualTo(SENSOR_NAME); + Assertions.assertThat(savedSensor.getSensorType()).isNotNull(); + Assertions.assertThat(savedSensor.getSensorType()).isEqualTo(SENSOR_TYPE); Mockito.verify(lightSensorRepository).save(sensor); } @@ -97,41 +94,13 @@ void expect_handleCreateSensor_withNonExistingCamera_throwsCameraNotFoundExcepti Mockito.verify(lightSensorRepository).save(sensor); } - @Test - void expect_handleCreateSensor_withNullSensorName_throwsException() { - - // arrange - sensor.setName(null); - Mockito.when(lightSensorRepository.save(sensor)).thenThrow(new SensorNotCreatedException("Sensor name cannot be null")); - - // act and assert - Assertions.assertThatThrownBy(() -> lightSensorService.handleCreateSensor(CAMERA_ID, sensor)) - .isInstanceOf(SensorNotCreatedException.class); - - Mockito.verify(lightSensorRepository).save(sensor); - } - - @Test - void expect_handleCreateSensor_withNullSensorType_throwsException() { - - // arrange - sensor.setSensorType(null); - Mockito.when(lightSensorRepository.save(sensor)).thenThrow(new SensorNotCreatedException("Sensor type cannot be null")); - - // act and assert - Assertions.assertThatThrownBy(() -> lightSensorService.handleCreateSensor(CAMERA_ID, sensor)) - .isInstanceOf(SensorNotCreatedException.class); - - Mockito.verify(lightSensorRepository).save(sensor); - } - @Test void expect_handleUpdateSensor_withValidData_returnsUpdatedSensor() { // arrange sensor.setCamera(camera); - sensor.setName("Updated Name"); - sensor.setVersion("v1.1"); - sensor.setData("Updated Data"); + sensor.setName(UPDATED_SENSOR_NAME); + sensor.setVersion(SENSOR_VERSION); + sensor.setData(UPDATED_SENSOR_DATA); Mockito.when(cameraService.getCameraById(CAMERA_ID)).thenReturn(camera); Mockito.when(lightSensorRepository.save(sensor)).thenReturn(sensor); Mockito.when(camera.getSensors()).thenReturn(new ArrayList<>(List.of(sensor))); @@ -140,29 +109,16 @@ void expect_handleUpdateSensor_withValidData_returnsUpdatedSensor() { LightSensor updatedSensor = lightSensorService.handleUpdateSensor(CAMERA_ID, SENSOR_ID, sensor); // assert - Assertions.assertThat(updatedSensor) - .isNotNull() - .satisfies(sensor -> { - Assertions.assertThat(sensor.getName()) - .as("Check Sensor Name") - .isNotNull() - .isEqualTo("Updated Name"); - - Assertions.assertThat(sensor.getVersion()) - .as("Check Sensor Version") - .isNotNull() - .isEqualTo("v1.1"); - - Assertions.assertThat(sensor.getCamera()) - .as("Check Sensor Camera") - .isNotNull() - .isEqualTo(camera); - - Assertions.assertThat(sensor.getData()) - .as("Check Sensor Data") - .isNotNull() - .isEqualTo("Updated Data"); - }); + Assertions.assertThat(updatedSensor).isNotNull(); + Assertions.assertThat(updatedSensor).isEqualTo(sensor); + Assertions.assertThat(updatedSensor.getName()).isNotNull(); + Assertions.assertThat(updatedSensor.getName()).isEqualTo(UPDATED_SENSOR_NAME); + Assertions.assertThat(updatedSensor.getVersion()).isNotNull(); + Assertions.assertThat(updatedSensor.getVersion()).isEqualTo(SENSOR_VERSION); + Assertions.assertThat(updatedSensor.getCamera()).isNotNull(); + Assertions.assertThat(updatedSensor.getCamera()).isEqualTo(camera); + Assertions.assertThat(updatedSensor.getData()).isNotNull(); + Assertions.assertThat(updatedSensor.getData()).isEqualTo(UPDATED_SENSOR_DATA); Mockito.verify(lightSensorRepository).save(sensor); } From e9dd43aedc58c3a825b9cf14dbb6d55e94e84b49 Mon Sep 17 00:00:00 2001 From: Selahattin <98191442+SelahattinSert@users.noreply.github.com> Date: Thu, 2 Jan 2025 01:54:30 +0300 Subject: [PATCH 35/40] Remove unused import --- .../controller/LightSensorControllerTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/onboarding/camera/cameraonboarding/controller/LightSensorControllerTest.java b/src/test/java/com/onboarding/camera/cameraonboarding/controller/LightSensorControllerTest.java index 4d3a6cd..5c3ce2d 100644 --- a/src/test/java/com/onboarding/camera/cameraonboarding/controller/LightSensorControllerTest.java +++ b/src/test/java/com/onboarding/camera/cameraonboarding/controller/LightSensorControllerTest.java @@ -14,7 +14,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentMatchers; -import org.mockito.BDDMockito; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.beans.factory.annotation.Autowired; @@ -155,8 +154,8 @@ void expect_getLightSensors_withValidCameraId_returnOk() throws Exception { sensor.setId(SENSOR_ID); sensor.setName(SENSOR_NAME); sensor.setSensorType(SENSOR_TYPE); - BDDMockito.given(lightSensorService.handleGetSensorsByCameraId(CAMERA_ID)) - .willReturn(Collections.singletonList(sensor)); + Mockito.when(lightSensorService.handleGetSensorsByCameraId(CAMERA_ID)) + .thenReturn(Collections.singletonList(sensor)); // act ResultActions response = mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/camera/{cameraId}/sensor/light", CAMERA_ID) From fe79fcf428fc6772597665cb61549b2da15735da Mon Sep 17 00:00:00 2001 From: Selahattin <98191442+SelahattinSert@users.noreply.github.com> Date: Thu, 2 Jan 2025 01:55:00 +0300 Subject: [PATCH 36/40] Add new test cases --- .../converter/SensorDtoConverterTest.java | 67 ++++++++++++++----- 1 file changed, 49 insertions(+), 18 deletions(-) diff --git a/src/test/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverterTest.java b/src/test/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverterTest.java index 5570135..3eaf573 100644 --- a/src/test/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverterTest.java +++ b/src/test/java/com/onboarding/camera/cameraonboarding/converter/SensorDtoConverterTest.java @@ -5,9 +5,9 @@ import com.onboarding.camera.cameraonboarding.entity.Sensor; import com.onboarding.camera.cameraonboarding.entity.TemperatureSensor; import com.onboarding.camera.cameraonboarding.enums.SensorType; +import com.onboarding.camera.cameraonboarding.exception.SensorMismatchException; import com.onboarding.camera.cameraonboarding.exception.SensorNotCreatedException; import org.assertj.core.api.Assertions; -import org.assertj.core.api.AssertionsForClassTypes; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -20,8 +20,9 @@ class SensorDtoConverterTest { private final UUID SENSOR_ID = UUID.randomUUID(); private final String SENSOR_NAME = "Sensor 1"; private final String SENSOR_VERSION = "v1.0"; - private final SensorType SENSOR_TYPE = SensorType.LIGHT; + private final SensorType SENSOR_TYPE_LIGHT = SensorType.LIGHT; private final String SENSOR_DATA = "Sensor data"; + private final SensorType SENSOR_TYPE_TEMPERATURE = SensorType.TEMPERATURE; @BeforeEach void setUp() { @@ -34,18 +35,18 @@ void expect_convert_withValidSensorDto_returnSensor() { SensorDto sensorDto = new SensorDto(); sensorDto.setName(SENSOR_NAME); sensorDto.setVersion(SENSOR_VERSION); - sensorDto.setSensorType(SENSOR_TYPE); + sensorDto.setSensorType(SENSOR_TYPE_LIGHT); sensorDto.setData(SENSOR_DATA); // act Sensor sensor = sensorDtoConverter.toLightEntity(sensorDto); // assert - AssertionsForClassTypes.assertThat(sensor).isNotNull(); - AssertionsForClassTypes.assertThat(sensor.getName()).isEqualTo(SENSOR_NAME); - AssertionsForClassTypes.assertThat(sensor.getVersion()).isEqualTo(SENSOR_VERSION); - AssertionsForClassTypes.assertThat(sensor.getSensorType()).isEqualTo(SENSOR_TYPE); - AssertionsForClassTypes.assertThat(sensor.getData()).isEqualTo(SENSOR_DATA); + Assertions.assertThat(sensor).isNotNull(); + Assertions.assertThat(sensor.getName()).isEqualTo(SENSOR_NAME); + Assertions.assertThat(sensor.getVersion()).isEqualTo(SENSOR_VERSION); + Assertions.assertThat(sensor.getSensorType()).isEqualTo(SENSOR_TYPE_LIGHT); + Assertions.assertThat(sensor.getData()).isEqualTo(SENSOR_DATA); } @Test @@ -55,23 +56,23 @@ void expect_convert_withValidSensor_returnSensorDto() { sensor.setId(SENSOR_ID); sensor.setName(SENSOR_NAME); sensor.setVersion(SENSOR_VERSION); - sensor.setSensorType(SENSOR_TYPE); + sensor.setSensorType(SENSOR_TYPE_LIGHT); sensor.setData(SENSOR_DATA); // act SensorResponse response = sensorDtoConverter.toSensorResponse(sensor); // assert - AssertionsForClassTypes.assertThat(response).isNotNull(); - AssertionsForClassTypes.assertThat(response.getId()).isEqualTo(SENSOR_ID); - AssertionsForClassTypes.assertThat(response.getName()).isEqualTo(SENSOR_NAME); - AssertionsForClassTypes.assertThat(response.getVersion()).isEqualTo(SENSOR_VERSION); - AssertionsForClassTypes.assertThat(response.getSensorType()).isEqualTo(SENSOR_TYPE); - AssertionsForClassTypes.assertThat(response.getData()).isEqualTo(SENSOR_DATA); + Assertions.assertThat(response).isNotNull(); + Assertions.assertThat(response.getId()).isEqualTo(SENSOR_ID); + Assertions.assertThat(response.getName()).isEqualTo(SENSOR_NAME); + Assertions.assertThat(response.getVersion()).isEqualTo(SENSOR_VERSION); + Assertions.assertThat(response.getSensorType()).isEqualTo(SENSOR_TYPE_LIGHT); + Assertions.assertThat(response.getData()).isEqualTo(SENSOR_DATA); } @Test - void expect_convert_withNullSensorName_throwsException() { + void expect_convert_withNullSensorName_throwsSensorNotCreatedException() { // arrange SensorDto sensorDto = new SensorDto(); sensorDto.setName(null); @@ -84,7 +85,7 @@ void expect_convert_withNullSensorName_throwsException() { } @Test - void expect_convert_withNullSensorVersion_throwsException() { + void expect_convert_withNullSensorVersion_throwsSensorNotCreatedException() { // arrange SensorDto sensorDto = new SensorDto(); sensorDto.setName(SENSOR_NAME); @@ -98,7 +99,7 @@ void expect_convert_withNullSensorVersion_throwsException() { } @Test - void expect_convert_withNullSensorType_throwsException() { + void expect_convert_withNullSensorType_throwsSensorNotCreatedException() { // arrange SensorDto sensorDto = new SensorDto(); sensorDto.setName(SENSOR_NAME); @@ -111,4 +112,34 @@ void expect_convert_withNullSensorType_throwsException() { .isInstanceOf(SensorNotCreatedException.class) .hasMessage("Sensor type cannot be null"); } + + @Test + void expect_convertToLightEntity_withWrongSensorType_throwsSensorMismatchException() { + // arrange + SensorDto sensorDto = new SensorDto(); + sensorDto.setName(SENSOR_NAME); + sensorDto.setVersion(SENSOR_VERSION); + sensorDto.setSensorType(SENSOR_TYPE_TEMPERATURE); + + + // act and assert + Assertions.assertThatThrownBy(() -> sensorDtoConverter.toLightEntity(sensorDto)) + .isInstanceOf(SensorMismatchException.class) + .hasMessage("Invalid sensor type for LightSensor"); + } + + @Test + void expect_convertToTemperatureEntity_withWrongSensorType_throwsSensorMismatchException() { + // arrange + SensorDto sensorDto = new SensorDto(); + sensorDto.setName(SENSOR_NAME); + sensorDto.setVersion(SENSOR_VERSION); + sensorDto.setSensorType(SENSOR_TYPE_LIGHT); + + + // act and assert + Assertions.assertThatThrownBy(() -> sensorDtoConverter.toTemperatureEntity(sensorDto)) + .isInstanceOf(SensorMismatchException.class) + .hasMessage("Invalid sensor type for TemperatureSensor"); + } } \ No newline at end of file From 7529618eecce4c7a3ae679b756fbe2ab32341a7b Mon Sep 17 00:00:00 2001 From: Selahattin <98191442+SelahattinSert@users.noreply.github.com> Date: Thu, 2 Jan 2025 01:55:22 +0300 Subject: [PATCH 37/40] Fix test methods --- .../repository/LightSensorRepositoryTest.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/onboarding/camera/cameraonboarding/repository/LightSensorRepositoryTest.java b/src/test/java/com/onboarding/camera/cameraonboarding/repository/LightSensorRepositoryTest.java index fb8db07..526b975 100644 --- a/src/test/java/com/onboarding/camera/cameraonboarding/repository/LightSensorRepositoryTest.java +++ b/src/test/java/com/onboarding/camera/cameraonboarding/repository/LightSensorRepositoryTest.java @@ -10,7 +10,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.dao.DataIntegrityViolationException; -import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.Optional; @@ -43,7 +42,6 @@ void setUp() { } @Test - @Transactional public void expect_save_sensorRepository_saveAll_returnsSavedSensor() { // act @@ -127,8 +125,8 @@ public void expect_delete_sensorWithExistingId_returnsVoid() { } @Test - @Transactional public void expect_deleteCamera_removesAssociatedSensors() { + // Arrange Camera camera = new Camera(); camera.setCamId(CAMERA_ID); @@ -146,11 +144,13 @@ public void expect_deleteCamera_removesAssociatedSensors() { sensor2.setSensorType(SENSOR_TYPE); sensor2.setCamera(camera); + camera.getSensors().add(sensor1); + camera.getSensors().add(sensor2); + lightSensorRepository.save(sensor1); lightSensorRepository.save(sensor2); // Act - lightSensorRepository.deleteAll(); cameraRepository.delete(camera); // Assert @@ -158,7 +158,6 @@ public void expect_deleteCamera_removesAssociatedSensors() { } @Test - @Transactional public void expect_findLightSensorsByCamera_returnsLightSensors() { // Arrange Camera camera = new Camera(); @@ -190,7 +189,6 @@ public void expect_findLightSensorsByCamera_returnsLightSensors() { } @Test - @Transactional public void expect_updateSensor_withValidSensor_returnsUpdatedSensor() { // Arrange LightSensor savedSensor = lightSensorRepository.save(lightSensor); From 01d7d733725432833952b0c93689f787b491b73f Mon Sep 17 00:00:00 2001 From: Selahattin <98191442+SelahattinSert@users.noreply.github.com> Date: Sat, 4 Jan 2025 02:59:59 +0300 Subject: [PATCH 38/40] Add motion and temperature sensor controller tests --- .../MotionSensorControllerTest.java | 327 ++++++++++++++++++ .../TemperatureSensorControllerTest.java | 327 ++++++++++++++++++ 2 files changed, 654 insertions(+) create mode 100644 src/test/java/com/onboarding/camera/cameraonboarding/controller/MotionSensorControllerTest.java create mode 100644 src/test/java/com/onboarding/camera/cameraonboarding/controller/TemperatureSensorControllerTest.java diff --git a/src/test/java/com/onboarding/camera/cameraonboarding/controller/MotionSensorControllerTest.java b/src/test/java/com/onboarding/camera/cameraonboarding/controller/MotionSensorControllerTest.java new file mode 100644 index 0000000..ea78dd4 --- /dev/null +++ b/src/test/java/com/onboarding/camera/cameraonboarding/controller/MotionSensorControllerTest.java @@ -0,0 +1,327 @@ +package com.onboarding.camera.cameraonboarding.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.onboarding.camera.cameraonboarding.converter.SensorDtoConverter; +import com.onboarding.camera.cameraonboarding.dto.SensorDto; +import com.onboarding.camera.cameraonboarding.entity.Camera; +import com.onboarding.camera.cameraonboarding.entity.MotionSensor; +import com.onboarding.camera.cameraonboarding.enums.SensorType; +import com.onboarding.camera.cameraonboarding.exception.SensorNotCreatedException; +import com.onboarding.camera.cameraonboarding.exception.SensorNotUpdatedException; +import com.onboarding.camera.cameraonboarding.service.impl.MotionSensorService; +import org.hamcrest.CoreMatchers; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentMatchers; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import java.util.Collections; +import java.util.UUID; + +@WebMvcTest(controllers = MotionSensorController.class) +@AutoConfigureMockMvc(addFilters = false) +@ExtendWith(MockitoExtension.class) +@Import(SensorDtoConverter.class) +class MotionSensorControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private MotionSensorService motionSensorService; + + @Autowired + private ObjectMapper objectMapper; + + private SensorDto sensorDto; + + private MotionSensor sensor; + + private Camera camera; + + private final UUID SENSOR_ID = UUID.randomUUID(); + private final String SENSOR_NAME = "Motion Sensor 1"; + private final SensorType SENSOR_TYPE = SensorType.MOTION; + private final String SENSOR_VERSION = "v1.0"; + private final UUID CAMERA_ID = UUID.randomUUID(); + private final String CAMERA_NAME = "Camera 1"; + private final String FIRMWARE_VERSION = "v1.0.0"; + + @BeforeEach + void setUp() { + sensorDto = new SensorDto(); + sensorDto.setName(SENSOR_NAME); + sensorDto.setSensorType(SENSOR_TYPE); + sensorDto.setVersion(SENSOR_VERSION); + sensor = new MotionSensor(); + camera = new Camera(); + camera.setCamId(CAMERA_ID); + camera.setCameraName(CAMERA_NAME); + camera.setFirmwareVersion(FIRMWARE_VERSION); + } + + @Test + public void expect_handleCreateSensor_withValidSensorDto_returnCreated() throws Exception { + + // arrange + sensor.setId(SENSOR_ID); + sensor.setName(SENSOR_NAME); + sensor.setSensorType(SENSOR_TYPE); + Mockito.when(motionSensorService.handleCreateSensor(Mockito.eq(CAMERA_ID), ArgumentMatchers.any(MotionSensor.class))).thenReturn(sensor); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/camera/{cameraId}/sensor/motion", CAMERA_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isCreated()) + .andExpect(MockMvcResultMatchers.jsonPath("$.id", CoreMatchers.is(SENSOR_ID.toString()))) + .andExpect(MockMvcResultMatchers.jsonPath("$.name", CoreMatchers.is(SENSOR_NAME))) + .andExpect(MockMvcResultMatchers.jsonPath("$.sensorType", CoreMatchers.is(SENSOR_TYPE.toString()))); + + Mockito.verify(motionSensorService).handleCreateSensor(Mockito.eq(CAMERA_ID), ArgumentMatchers.any(MotionSensor.class)); + } + + @Test + public void expect_handleCreateSensor_withNullSensorName_returnBadRequest() throws Exception { + + // arrange + sensorDto.setName(null); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/camera/{cameraId}/sensor/motion", CAMERA_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isBadRequest()); + + Mockito.verify(motionSensorService, Mockito.never()).handleCreateSensor(Mockito.eq(CAMERA_ID), ArgumentMatchers.any(MotionSensor.class)); + } + + @Test + public void expect_handleCreateSensor_withNullSensorType_returnBadRequest() throws Exception { + + // arrange + sensorDto.setSensorType(null); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/camera/{cameraId}/sensor/motion", CAMERA_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isBadRequest()); + + Mockito.verify(motionSensorService, Mockito.never()).handleCreateSensor(Mockito.eq(CAMERA_ID), ArgumentMatchers.any(MotionSensor.class)); + } + + @Test + void expect_handleCreateMotionSensor_withSensorNotCreatedException_returnInternalServerError() throws Exception { + + // arrange + Mockito.doThrow(new SensorNotCreatedException("Failed to create sensor")) + .when(motionSensorService).handleCreateSensor(ArgumentMatchers.eq(CAMERA_ID), ArgumentMatchers.any(MotionSensor.class)); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/camera/{cameraId}/sensor/motion", CAMERA_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isInternalServerError()); + + Mockito.verify(motionSensorService).handleCreateSensor(ArgumentMatchers.eq(CAMERA_ID), ArgumentMatchers.any(MotionSensor.class)); + } + + @Test + void expect_getMotionSensors_withValidCameraId_returnOk() throws Exception { + + // arrange + sensor.setId(SENSOR_ID); + sensor.setName(SENSOR_NAME); + sensor.setSensorType(SENSOR_TYPE); + Mockito.when(motionSensorService.handleGetSensorsByCameraId(CAMERA_ID)) + .thenReturn(Collections.singletonList(sensor)); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/camera/{cameraId}/sensor/motion", CAMERA_ID) + .contentType(MediaType.APPLICATION_JSON)); + + // assert + response.andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].id", CoreMatchers.is(SENSOR_ID.toString()))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].name", CoreMatchers.is(SENSOR_NAME))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sensorType", CoreMatchers.is(SENSOR_TYPE.toString()))); + + Mockito.verify(motionSensorService).handleGetSensorsByCameraId(CAMERA_ID); + } + + @Test + void expect_getMotionSensors_withNullCameraId_returnNotFound() throws Exception { + + // arrange + camera.setCamId(null); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/camera/{cameraId}/sensor/motion", camera.getCamId()) + .contentType(MediaType.APPLICATION_JSON)); + + // assert + response.andExpect(MockMvcResultMatchers.status().isNotFound()); + } + + @Test + void expect_handleUpdateMotionSensor_withValidRequest_returnOk() throws Exception { + + // arrange + sensor.setId(SENSOR_ID); + String updatedName = "Updated Name"; + sensor.setName(updatedName); + sensor.setSensorType(SENSOR_TYPE); + Mockito.when(motionSensorService.handleUpdateSensor(Mockito.eq(CAMERA_ID), Mockito.eq(SENSOR_ID), ArgumentMatchers.any(MotionSensor.class))) + .thenReturn(sensor); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.put("/api/v1/camera/{cameraId}/sensor/motion/{sensorId}", CAMERA_ID, SENSOR_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.id", CoreMatchers.is(SENSOR_ID.toString()))) + .andExpect(MockMvcResultMatchers.jsonPath("$.name", CoreMatchers.is(updatedName))) + .andExpect(MockMvcResultMatchers.jsonPath("$.sensorType", CoreMatchers.is(SENSOR_TYPE.toString()))); + + Mockito.verify(motionSensorService).handleUpdateSensor(Mockito.eq(CAMERA_ID), Mockito.eq(SENSOR_ID), ArgumentMatchers.any(MotionSensor.class)); + } + + @Test + void expect_handleUpdateMotionSensor_withNullSensorId_returnNotFound() throws Exception { + + // arrange + sensor.setId(null); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.put("/api/v1/camera/{cameraId}/sensor/motion/{sensorId}", CAMERA_ID, sensor.getId()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isNotFound()); + + Mockito.verify(motionSensorService, Mockito.never()).handleUpdateSensor(Mockito.eq(CAMERA_ID), Mockito.eq(sensor.getId()), ArgumentMatchers.any(MotionSensor.class)); + } + + @Test + void expect_handleUpdateMotionSensor_withNullCameraId_returnNotFound() throws Exception { + + // arrange + camera.setCamId(null); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.put("/api/v1/camera/{cameraId}/sensor/motion/{sensorId}", camera.getCamId(), SENSOR_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isNotFound()); + + Mockito.verify(motionSensorService, Mockito.never()).handleUpdateSensor(Mockito.eq(camera.getCamId()), Mockito.eq(SENSOR_ID), ArgumentMatchers.any(MotionSensor.class)); + } + + @Test + void expect_handleUpdateMotionSensor_withSensorNotUpdatedException_returnInternalServerError() throws Exception { + + // arrange + Mockito.doThrow(new SensorNotUpdatedException("Error occurred while deleting sensor")) + .when(motionSensorService).handleUpdateSensor(ArgumentMatchers.eq(CAMERA_ID), ArgumentMatchers.eq(SENSOR_ID), ArgumentMatchers.any(MotionSensor.class)); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.put("/api/v1/camera/{cameraId}/sensor/motion/{sensorId}", CAMERA_ID, SENSOR_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isInternalServerError()); + + Mockito.verify(motionSensorService).handleUpdateSensor(ArgumentMatchers.eq(CAMERA_ID), ArgumentMatchers.eq(SENSOR_ID), ArgumentMatchers.any(MotionSensor.class)); + } + + @Test + void expect_handleDeleteMotionSensor_withValidRequest_returnNoContent() throws Exception { + // Act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.delete("/api/v1/camera/{cameraId}/sensor/motion/{sensorId}", CAMERA_ID, SENSOR_ID) + .contentType(MediaType.APPLICATION_JSON)); + + // Assert + response.andExpect(MockMvcResultMatchers.status().isNoContent()); + + Mockito.verify(motionSensorService).handleDeleteSensor(CAMERA_ID, SENSOR_ID); + } + + @Test + void expect_handleDeleteMotionSensor_withNullSensorId_returnNotFound() throws Exception { + + // arrange + sensor.setId(null); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.delete("/api/v1/camera/{cameraId}/sensor/motion/{sensorId}", CAMERA_ID, sensor.getId()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isNotFound()); + + Mockito.verify(motionSensorService, Mockito.never()).handleDeleteSensor(Mockito.eq(CAMERA_ID), Mockito.eq(sensor.getId())); + } + + @Test + void expect_handleDeleteMotionSensor_withNullCameraId_returnNotFound() throws Exception { + + // arrange + camera.setCamId(null); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.delete("/api/v1/camera/{cameraId}/sensor/motion/{sensorId}", camera.getCamId(), SENSOR_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isNotFound()); + + Mockito.verify(motionSensorService, Mockito.never()).handleDeleteSensor(Mockito.eq(camera.getCamId()), Mockito.eq(SENSOR_ID)); + } + + @Test + void expect_handleDeleteMotionSensor_withSensorNotUpdatedException_returnInternalServerError() throws Exception { + + // arrange + Mockito.doThrow(new SensorNotUpdatedException("Error occurred while deleting sensor")) + .when(motionSensorService).handleDeleteSensor(CAMERA_ID, SENSOR_ID); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.delete("/api/v1/camera/{cameraId}/sensor/motion/{sensorId}", camera.getCamId(), SENSOR_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isInternalServerError()); + + Mockito.verify(motionSensorService).handleDeleteSensor(ArgumentMatchers.eq(CAMERA_ID), ArgumentMatchers.eq(SENSOR_ID)); + } +} \ No newline at end of file diff --git a/src/test/java/com/onboarding/camera/cameraonboarding/controller/TemperatureSensorControllerTest.java b/src/test/java/com/onboarding/camera/cameraonboarding/controller/TemperatureSensorControllerTest.java new file mode 100644 index 0000000..cc75675 --- /dev/null +++ b/src/test/java/com/onboarding/camera/cameraonboarding/controller/TemperatureSensorControllerTest.java @@ -0,0 +1,327 @@ +package com.onboarding.camera.cameraonboarding.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.onboarding.camera.cameraonboarding.converter.SensorDtoConverter; +import com.onboarding.camera.cameraonboarding.dto.SensorDto; +import com.onboarding.camera.cameraonboarding.entity.Camera; +import com.onboarding.camera.cameraonboarding.entity.TemperatureSensor; +import com.onboarding.camera.cameraonboarding.enums.SensorType; +import com.onboarding.camera.cameraonboarding.exception.SensorNotCreatedException; +import com.onboarding.camera.cameraonboarding.exception.SensorNotUpdatedException; +import com.onboarding.camera.cameraonboarding.service.impl.TemperatureSensorService; +import org.hamcrest.CoreMatchers; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentMatchers; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import java.util.Collections; +import java.util.UUID; + +@WebMvcTest(controllers = TemperatureSensorController.class) +@AutoConfigureMockMvc(addFilters = false) +@ExtendWith(MockitoExtension.class) +@Import(SensorDtoConverter.class) +class TemperatureSensorControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private TemperatureSensorService temperatureSensorService; + + @Autowired + private ObjectMapper objectMapper; + + private SensorDto sensorDto; + + private TemperatureSensor sensor; + + private Camera camera; + + private final UUID SENSOR_ID = UUID.randomUUID(); + private final String SENSOR_NAME = "Temperature Sensor 1"; + private final SensorType SENSOR_TYPE = SensorType.TEMPERATURE; + private final String SENSOR_VERSION = "v1.0"; + private final UUID CAMERA_ID = UUID.randomUUID(); + private final String CAMERA_NAME = "Camera 1"; + private final String FIRMWARE_VERSION = "v1.0.0"; + + @BeforeEach + void setUp() { + sensorDto = new SensorDto(); + sensorDto.setName(SENSOR_NAME); + sensorDto.setSensorType(SENSOR_TYPE); + sensorDto.setVersion(SENSOR_VERSION); + sensor = new TemperatureSensor(); + camera = new Camera(); + camera.setCamId(CAMERA_ID); + camera.setCameraName(CAMERA_NAME); + camera.setFirmwareVersion(FIRMWARE_VERSION); + } + + @Test + public void expect_handleCreateSensor_withValidSensorDto_returnCreated() throws Exception { + + // arrange + sensor.setId(SENSOR_ID); + sensor.setName(SENSOR_NAME); + sensor.setSensorType(SENSOR_TYPE); + Mockito.when(temperatureSensorService.handleCreateSensor(Mockito.eq(CAMERA_ID), ArgumentMatchers.any(TemperatureSensor.class))).thenReturn(sensor); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/camera/{cameraId}/sensor/temperature", CAMERA_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isCreated()) + .andExpect(MockMvcResultMatchers.jsonPath("$.id", CoreMatchers.is(SENSOR_ID.toString()))) + .andExpect(MockMvcResultMatchers.jsonPath("$.name", CoreMatchers.is(SENSOR_NAME))) + .andExpect(MockMvcResultMatchers.jsonPath("$.sensorType", CoreMatchers.is(SENSOR_TYPE.toString()))); + + Mockito.verify(temperatureSensorService).handleCreateSensor(Mockito.eq(CAMERA_ID), ArgumentMatchers.any(TemperatureSensor.class)); + } + + @Test + public void expect_handleCreateSensor_withNullSensorName_returnBadRequest() throws Exception { + + // arrange + sensorDto.setName(null); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/camera/{cameraId}/sensor/temperature", CAMERA_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isBadRequest()); + + Mockito.verify(temperatureSensorService, Mockito.never()).handleCreateSensor(Mockito.eq(CAMERA_ID), ArgumentMatchers.any(TemperatureSensor.class)); + } + + @Test + public void expect_handleCreateSensor_withNullSensorType_returnBadRequest() throws Exception { + + // arrange + sensorDto.setSensorType(null); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/camera/{cameraId}/sensor/temperature", CAMERA_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isBadRequest()); + + Mockito.verify(temperatureSensorService, Mockito.never()).handleCreateSensor(Mockito.eq(CAMERA_ID), ArgumentMatchers.any(TemperatureSensor.class)); + } + + @Test + void expect_handleCreateTemperatureSensor_withSensorNotCreatedException_returnInternalServerError() throws Exception { + + // arrange + Mockito.doThrow(new SensorNotCreatedException("Failed to create sensor")) + .when(temperatureSensorService).handleCreateSensor(ArgumentMatchers.eq(CAMERA_ID), ArgumentMatchers.any(TemperatureSensor.class)); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/camera/{cameraId}/sensor/temperature", CAMERA_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isInternalServerError()); + + Mockito.verify(temperatureSensorService).handleCreateSensor(ArgumentMatchers.eq(CAMERA_ID), ArgumentMatchers.any(TemperatureSensor.class)); + } + + @Test + void expect_getTemperatureSensors_withValidCameraId_returnOk() throws Exception { + + // arrange + sensor.setId(SENSOR_ID); + sensor.setName(SENSOR_NAME); + sensor.setSensorType(SENSOR_TYPE); + Mockito.when(temperatureSensorService.handleGetSensorsByCameraId(CAMERA_ID)) + .thenReturn(Collections.singletonList(sensor)); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/camera/{cameraId}/sensor/temperature", CAMERA_ID) + .contentType(MediaType.APPLICATION_JSON)); + + // assert + response.andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].id", CoreMatchers.is(SENSOR_ID.toString()))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].name", CoreMatchers.is(SENSOR_NAME))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sensorType", CoreMatchers.is(SENSOR_TYPE.toString()))); + + Mockito.verify(temperatureSensorService).handleGetSensorsByCameraId(CAMERA_ID); + } + + @Test + void expect_getTemperatureSensors_withNullCameraId_returnNotFound() throws Exception { + + // arrange + camera.setCamId(null); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/camera/{cameraId}/sensor/temperature", camera.getCamId()) + .contentType(MediaType.APPLICATION_JSON)); + + // assert + response.andExpect(MockMvcResultMatchers.status().isNotFound()); + } + + @Test + void expect_handleUpdateTemperatureSensor_withValidRequest_returnOk() throws Exception { + + // arrange + sensor.setId(SENSOR_ID); + String updatedName = "Updated Name"; + sensor.setName(updatedName); + sensor.setSensorType(SENSOR_TYPE); + Mockito.when(temperatureSensorService.handleUpdateSensor(Mockito.eq(CAMERA_ID), Mockito.eq(SENSOR_ID), ArgumentMatchers.any(TemperatureSensor.class))) + .thenReturn(sensor); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.put("/api/v1/camera/{cameraId}/sensor/temperature/{sensorId}", CAMERA_ID, SENSOR_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.id", CoreMatchers.is(SENSOR_ID.toString()))) + .andExpect(MockMvcResultMatchers.jsonPath("$.name", CoreMatchers.is(updatedName))) + .andExpect(MockMvcResultMatchers.jsonPath("$.sensorType", CoreMatchers.is(SENSOR_TYPE.toString()))); + + Mockito.verify(temperatureSensorService).handleUpdateSensor(Mockito.eq(CAMERA_ID), Mockito.eq(SENSOR_ID), ArgumentMatchers.any(TemperatureSensor.class)); + } + + @Test + void expect_handleUpdateTemperatureSensor_withNullSensorId_returnNotFound() throws Exception { + + // arrange + sensor.setId(null); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.put("/api/v1/camera/{cameraId}/sensor/temperature/{sensorId}", CAMERA_ID, sensor.getId()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isNotFound()); + + Mockito.verify(temperatureSensorService, Mockito.never()).handleUpdateSensor(Mockito.eq(CAMERA_ID), Mockito.eq(sensor.getId()), ArgumentMatchers.any(TemperatureSensor.class)); + } + + @Test + void expect_handleUpdateTemperatureSensor_withNullCameraId_returnNotFound() throws Exception { + + // arrange + camera.setCamId(null); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.put("/api/v1/camera/{cameraId}/sensor/temperature/{sensorId}", camera.getCamId(), SENSOR_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isNotFound()); + + Mockito.verify(temperatureSensorService, Mockito.never()).handleUpdateSensor(Mockito.eq(camera.getCamId()), Mockito.eq(SENSOR_ID), ArgumentMatchers.any(TemperatureSensor.class)); + } + + @Test + void expect_handleUpdateTemperatureSensor_withSensorNotUpdatedException_returnInternalServerError() throws Exception { + + // arrange + Mockito.doThrow(new SensorNotUpdatedException("Error occurred while deleting sensor")) + .when(temperatureSensorService).handleUpdateSensor(ArgumentMatchers.eq(CAMERA_ID), ArgumentMatchers.eq(SENSOR_ID), ArgumentMatchers.any(TemperatureSensor.class)); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.put("/api/v1/camera/{cameraId}/sensor/temperature/{sensorId}", CAMERA_ID, SENSOR_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isInternalServerError()); + + Mockito.verify(temperatureSensorService).handleUpdateSensor(ArgumentMatchers.eq(CAMERA_ID), ArgumentMatchers.eq(SENSOR_ID), ArgumentMatchers.any(TemperatureSensor.class)); + } + + @Test + void expect_handleDeleteTemperatureSensor_withValidRequest_returnNoContent() throws Exception { + // Act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.delete("/api/v1/camera/{cameraId}/sensor/temperature/{sensorId}", CAMERA_ID, SENSOR_ID) + .contentType(MediaType.APPLICATION_JSON)); + + // Assert + response.andExpect(MockMvcResultMatchers.status().isNoContent()); + + Mockito.verify(temperatureSensorService).handleDeleteSensor(CAMERA_ID, SENSOR_ID); + } + + @Test + void expect_handleDeleteTemperatureSensor_withNullSensorId_returnNotFound() throws Exception { + + // arrange + sensor.setId(null); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.delete("/api/v1/camera/{cameraId}/sensor/temperature/{sensorId}", CAMERA_ID, sensor.getId()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isNotFound()); + + Mockito.verify(temperatureSensorService, Mockito.never()).handleDeleteSensor(Mockito.eq(CAMERA_ID), Mockito.eq(sensor.getId())); + } + + @Test + void expect_handleDeleteTemperatureSensor_withNullCameraId_returnNotFound() throws Exception { + + // arrange + camera.setCamId(null); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.delete("/api/v1/camera/{cameraId}/sensor/temperature/{sensorId}", camera.getCamId(), SENSOR_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isNotFound()); + + Mockito.verify(temperatureSensorService, Mockito.never()).handleDeleteSensor(Mockito.eq(camera.getCamId()), Mockito.eq(SENSOR_ID)); + } + + @Test + void expect_handleDeleteTemperatureSensor_withSensorNotUpdatedException_returnInternalServerError() throws Exception { + + // arrange + Mockito.doThrow(new SensorNotUpdatedException("Error occurred while deleting sensor")) + .when(temperatureSensorService).handleDeleteSensor(CAMERA_ID, SENSOR_ID); + + // act + ResultActions response = mockMvc.perform(MockMvcRequestBuilders.delete("/api/v1/camera/{cameraId}/sensor/temperature/{sensorId}", camera.getCamId(), SENSOR_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sensorDto))); + + // assert + response.andExpect(MockMvcResultMatchers.status().isInternalServerError()); + + Mockito.verify(temperatureSensorService).handleDeleteSensor(ArgumentMatchers.eq(CAMERA_ID), ArgumentMatchers.eq(SENSOR_ID)); + } +} \ No newline at end of file From 131ee0d3b2f702c7e0a993de27524556e23c24f0 Mon Sep 17 00:00:00 2001 From: Selahattin <98191442+SelahattinSert@users.noreply.github.com> Date: Sat, 4 Jan 2025 03:00:37 +0300 Subject: [PATCH 39/40] Add motion and temperature sensor repository tests --- .../MotionSensorRepositoryTest.java | 211 ++++++++++++++++++ .../TemperatureSensorRepositoryTest.java | 211 ++++++++++++++++++ 2 files changed, 422 insertions(+) create mode 100644 src/test/java/com/onboarding/camera/cameraonboarding/repository/MotionSensorRepositoryTest.java create mode 100644 src/test/java/com/onboarding/camera/cameraonboarding/repository/TemperatureSensorRepositoryTest.java diff --git a/src/test/java/com/onboarding/camera/cameraonboarding/repository/MotionSensorRepositoryTest.java b/src/test/java/com/onboarding/camera/cameraonboarding/repository/MotionSensorRepositoryTest.java new file mode 100644 index 0000000..59d9bbd --- /dev/null +++ b/src/test/java/com/onboarding/camera/cameraonboarding/repository/MotionSensorRepositoryTest.java @@ -0,0 +1,211 @@ +package com.onboarding.camera.cameraonboarding.repository; + +import com.onboarding.camera.cameraonboarding.entity.Camera; +import com.onboarding.camera.cameraonboarding.entity.MotionSensor; +import com.onboarding.camera.cameraonboarding.entity.Sensor; +import com.onboarding.camera.cameraonboarding.enums.SensorType; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.dao.DataIntegrityViolationException; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +@DataJpaTest +class MotionSensorRepositoryTest { + + @Autowired + MotionSensorRepository motionSensorRepository; + + @Autowired + CameraRepository cameraRepository; + + private MotionSensor motionSensor; + + private final String SENSOR_NAME = "Motion Sensor 1"; + private final String SENSOR_NAME_2 = "Motion Sensor 2"; + private final SensorType SENSOR_TYPE = SensorType.MOTION; + private final UUID NON_EXISTING_UUID = UUID.fromString("ef556dc0-0ddc-4f39-a96d-6886a54eee54"); + private final UUID CAMERA_ID = UUID.randomUUID(); + private final String CAMERA_NAME = "Camera 1"; + private final String FIRMWARE_VERSION = "v1.0"; + + @BeforeEach + void setUp() { + motionSensor = new MotionSensor(); + motionSensor.setName(SENSOR_NAME); + motionSensor.setSensorType(SENSOR_TYPE); + } + + @Test + public void expect_save_sensorRepository_saveAll_returnsSavedSensor() { + + // act + Sensor savedSensor = motionSensorRepository.save(motionSensor); + + // assert + Assertions.assertThat(savedSensor).isNotNull(); + Assertions.assertThat(savedSensor.getName()).isNotNull(); + Assertions.assertThat(savedSensor.getName()).isEqualTo(SENSOR_NAME); + Assertions.assertThat(savedSensor.getSensorType()).isNotNull(); + Assertions.assertThat(savedSensor.getSensorType()).isEqualTo(SENSOR_TYPE); + Assertions.assertThat(savedSensor.getId()).isNotNull(); + } + + @Test + public void expect_save_sensorWithNullName_throwsException() { + + // arrange + motionSensor.setName(null); + + // act and assert + Assertions.assertThatThrownBy(() -> + motionSensorRepository.saveAndFlush(motionSensor) + ).isInstanceOf(DataIntegrityViolationException.class); + } + + @Test + public void expect_save_sensorWithNullType_throwsException() { + + // arrange + motionSensor.setSensorType(null); + + // act and assert + Assertions.assertThatThrownBy(() -> + motionSensorRepository.saveAndFlush(motionSensor) + ).isInstanceOf(DataIntegrityViolationException.class); + } + + @Test + public void expect_findById_motionSensorRepository_returnsSensor() { + + // arrange + motionSensorRepository.save(motionSensor); + + // act + Optional foundSensor = motionSensorRepository.findById(motionSensor.getId()); + + //assert + Assertions.assertThat(foundSensor).isPresent(); + Assertions.assertThat(foundSensor.get().getId()).isEqualTo(motionSensor.getId()); + } + + @Test + public void expect_findById_sensorWithNotExistingId_throwsException() { + + // act + Optional foundSensor = motionSensorRepository.findById(NON_EXISTING_UUID); + + // assert + Assertions.assertThat(foundSensor).isEmpty(); + } + + @Test + public void expect_delete_sensorWithExistingId_returnsVoid() { + + // Arrange + MotionSensor savedSensor = motionSensorRepository.save(motionSensor); + Camera associatedCamera = new Camera(); + associatedCamera.setCamId(CAMERA_ID); + associatedCamera.setCameraName(CAMERA_NAME); + associatedCamera.setFirmwareVersion(FIRMWARE_VERSION); + savedSensor.setCamera(associatedCamera); + motionSensorRepository.save(savedSensor); + + // Act + motionSensorRepository.delete(savedSensor); + + // Assert + Optional foundSensor = motionSensorRepository.findById(savedSensor.getId()); + Assertions.assertThat(foundSensor).isEmpty(); + } + + @Test + public void expect_deleteCamera_removesAssociatedSensors() { + + // Arrange + Camera camera = new Camera(); + camera.setCamId(CAMERA_ID); + camera.setCameraName(CAMERA_NAME); + camera.setFirmwareVersion(FIRMWARE_VERSION); + camera = cameraRepository.save(camera); + + MotionSensor sensor1 = new MotionSensor(); + sensor1.setName(SENSOR_NAME); + sensor1.setSensorType(SENSOR_TYPE); + sensor1.setCamera(camera); + + MotionSensor sensor2 = new MotionSensor(); + sensor2.setName(SENSOR_NAME_2); + sensor2.setSensorType(SENSOR_TYPE); + sensor2.setCamera(camera); + + camera.getSensors().add(sensor1); + camera.getSensors().add(sensor2); + + motionSensorRepository.save(sensor1); + motionSensorRepository.save(sensor2); + + // Act + cameraRepository.delete(camera); + + // Assert + Assertions.assertThat(motionSensorRepository.findMotionSensorByCamera(camera)).isEmpty(); + } + + @Test + public void expect_findMotionSensorsByCamera_returnsMotionSensors() { + // Arrange + Camera camera = new Camera(); + camera.setCamId(CAMERA_ID); + camera.setCameraName(CAMERA_NAME); + camera.setFirmwareVersion(FIRMWARE_VERSION); + Camera savedCamera = cameraRepository.save(camera); + + MotionSensor sensor1 = new MotionSensor(); + sensor1.setName(SENSOR_NAME); + sensor1.setSensorType(SENSOR_TYPE); + sensor1.setCamera(savedCamera); + + MotionSensor sensor2 = new MotionSensor(); + sensor2.setName(SENSOR_NAME_2); + sensor2.setSensorType(SENSOR_TYPE); + sensor2.setCamera(savedCamera); + + motionSensorRepository.save(sensor1); + motionSensorRepository.save(sensor2); + + // Act + List sensors = motionSensorRepository.findMotionSensorByCamera(savedCamera); + + // Assert + Assertions.assertThat(sensors).hasSize(2); + Assertions.assertThat(sensors).extracting(MotionSensor::getName) + .containsExactlyInAnyOrder(SENSOR_NAME, SENSOR_NAME_2); + } + + @Test + public void expect_updateSensor_withValidSensor_returnsUpdatedSensor() { + // Arrange + MotionSensor savedSensor = motionSensorRepository.save(motionSensor); + String updatedName = "Updated Sensor Name"; + String updatedSensorVersion = "v1.1"; + String updatedSensorData = "Sensor Data"; + + // Act + savedSensor.setName(updatedName); + savedSensor.setVersion(updatedSensorVersion); + savedSensor.setData(updatedSensorData); + MotionSensor updatedSensor = motionSensorRepository.save(savedSensor); + + // Assert + Assertions.assertThat(updatedSensor).isNotNull(); + Assertions.assertThat(updatedSensor.getName()).isEqualTo(updatedName); + Assertions.assertThat(updatedSensor.getVersion()).isEqualTo(updatedSensorVersion); + Assertions.assertThat(updatedSensor.getData()).isEqualTo(updatedSensorData); + } +} \ No newline at end of file diff --git a/src/test/java/com/onboarding/camera/cameraonboarding/repository/TemperatureSensorRepositoryTest.java b/src/test/java/com/onboarding/camera/cameraonboarding/repository/TemperatureSensorRepositoryTest.java new file mode 100644 index 0000000..5df5764 --- /dev/null +++ b/src/test/java/com/onboarding/camera/cameraonboarding/repository/TemperatureSensorRepositoryTest.java @@ -0,0 +1,211 @@ +package com.onboarding.camera.cameraonboarding.repository; + +import com.onboarding.camera.cameraonboarding.entity.Camera; +import com.onboarding.camera.cameraonboarding.entity.Sensor; +import com.onboarding.camera.cameraonboarding.entity.TemperatureSensor; +import com.onboarding.camera.cameraonboarding.enums.SensorType; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.dao.DataIntegrityViolationException; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +@DataJpaTest +class TemperatureSensorRepositoryTest { + + @Autowired + TemperatureSensorRepository temperatureSensorRepository; + + @Autowired + CameraRepository cameraRepository; + + private TemperatureSensor temperatureSensor; + + private final String SENSOR_NAME = "Temperature Sensor 1"; + private final String SENSOR_NAME_2 = "Temperature Sensor 2"; + private final SensorType SENSOR_TYPE = SensorType.TEMPERATURE; + private final UUID NON_EXISTING_UUID = UUID.fromString("ef556dc0-0ddc-4f39-a96d-6886a54eee54"); + private final UUID CAMERA_ID = UUID.randomUUID(); + private final String CAMERA_NAME = "Camera 1"; + private final String FIRMWARE_VERSION = "v1.0"; + + @BeforeEach + void setUp() { + temperatureSensor = new TemperatureSensor(); + temperatureSensor.setName(SENSOR_NAME); + temperatureSensor.setSensorType(SENSOR_TYPE); + } + + @Test + public void expect_save_sensorRepository_saveAll_returnsSavedSensor() { + + // act + Sensor savedSensor = temperatureSensorRepository.save(temperatureSensor); + + // assert + Assertions.assertThat(savedSensor).isNotNull(); + Assertions.assertThat(savedSensor.getName()).isNotNull(); + Assertions.assertThat(savedSensor.getName()).isEqualTo(SENSOR_NAME); + Assertions.assertThat(savedSensor.getSensorType()).isNotNull(); + Assertions.assertThat(savedSensor.getSensorType()).isEqualTo(SENSOR_TYPE); + Assertions.assertThat(savedSensor.getId()).isNotNull(); + } + + @Test + public void expect_save_sensorWithNullName_throwsException() { + + // arrange + temperatureSensor.setName(null); + + // act and assert + Assertions.assertThatThrownBy(() -> + temperatureSensorRepository.saveAndFlush(temperatureSensor) + ).isInstanceOf(DataIntegrityViolationException.class); + } + + @Test + public void expect_save_sensorWithNullType_throwsException() { + + // arrange + temperatureSensor.setSensorType(null); + + // act and assert + Assertions.assertThatThrownBy(() -> + temperatureSensorRepository.saveAndFlush(temperatureSensor) + ).isInstanceOf(DataIntegrityViolationException.class); + } + + @Test + public void expect_findById_temperatureSensorRepository_returnsSensor() { + + // arrange + temperatureSensorRepository.save(temperatureSensor); + + // act + Optional foundSensor = temperatureSensorRepository.findById(temperatureSensor.getId()); + + //assert + Assertions.assertThat(foundSensor).isPresent(); + Assertions.assertThat(foundSensor.get().getId()).isEqualTo(temperatureSensor.getId()); + } + + @Test + public void expect_findById_sensorWithNotExistingId_throwsException() { + + // act + Optional foundSensor = temperatureSensorRepository.findById(NON_EXISTING_UUID); + + // assert + Assertions.assertThat(foundSensor).isEmpty(); + } + + @Test + public void expect_delete_sensorWithExistingId_returnsVoid() { + + // Arrange + TemperatureSensor savedSensor = temperatureSensorRepository.save(temperatureSensor); + Camera associatedCamera = new Camera(); + associatedCamera.setCamId(CAMERA_ID); + associatedCamera.setCameraName(CAMERA_NAME); + associatedCamera.setFirmwareVersion(FIRMWARE_VERSION); + savedSensor.setCamera(associatedCamera); + temperatureSensorRepository.save(savedSensor); + + // Act + temperatureSensorRepository.delete(savedSensor); + + // Assert + Optional foundSensor = temperatureSensorRepository.findById(savedSensor.getId()); + Assertions.assertThat(foundSensor).isEmpty(); + } + + @Test + public void expect_deleteCamera_removesAssociatedSensors() { + + // Arrange + Camera camera = new Camera(); + camera.setCamId(CAMERA_ID); + camera.setCameraName(CAMERA_NAME); + camera.setFirmwareVersion(FIRMWARE_VERSION); + camera = cameraRepository.save(camera); + + TemperatureSensor sensor1 = new TemperatureSensor(); + sensor1.setName(SENSOR_NAME); + sensor1.setSensorType(SENSOR_TYPE); + sensor1.setCamera(camera); + + TemperatureSensor sensor2 = new TemperatureSensor(); + sensor2.setName(SENSOR_NAME_2); + sensor2.setSensorType(SENSOR_TYPE); + sensor2.setCamera(camera); + + camera.getSensors().add(sensor1); + camera.getSensors().add(sensor2); + + temperatureSensorRepository.save(sensor1); + temperatureSensorRepository.save(sensor2); + + // Act + cameraRepository.delete(camera); + + // Assert + Assertions.assertThat(temperatureSensorRepository.findTemperatureSensorByCamera(camera)).isEmpty(); + } + + @Test + public void expect_findTemperatureSensorsByCamera_returnsTemperatureSensors() { + // Arrange + Camera camera = new Camera(); + camera.setCamId(CAMERA_ID); + camera.setCameraName(CAMERA_NAME); + camera.setFirmwareVersion(FIRMWARE_VERSION); + Camera savedCamera = cameraRepository.save(camera); + + TemperatureSensor sensor1 = new TemperatureSensor(); + sensor1.setName(SENSOR_NAME); + sensor1.setSensorType(SENSOR_TYPE); + sensor1.setCamera(savedCamera); + + TemperatureSensor sensor2 = new TemperatureSensor(); + sensor2.setName(SENSOR_NAME_2); + sensor2.setSensorType(SENSOR_TYPE); + sensor2.setCamera(savedCamera); + + temperatureSensorRepository.save(sensor1); + temperatureSensorRepository.save(sensor2); + + // Act + List sensors = temperatureSensorRepository.findTemperatureSensorByCamera(savedCamera); + + // Assert + Assertions.assertThat(sensors).hasSize(2); + Assertions.assertThat(sensors).extracting(TemperatureSensor::getName) + .containsExactlyInAnyOrder(SENSOR_NAME, SENSOR_NAME_2); + } + + @Test + public void expect_updateSensor_withValidSensor_returnsUpdatedSensor() { + // Arrange + TemperatureSensor savedSensor = temperatureSensorRepository.save(temperatureSensor); + String updatedName = "Updated Sensor Name"; + String updatedSensorVersion = "v1.1"; + String updatedSensorData = "Sensor Data"; + + // Act + savedSensor.setName(updatedName); + savedSensor.setVersion(updatedSensorVersion); + savedSensor.setData(updatedSensorData); + TemperatureSensor updatedSensor = temperatureSensorRepository.save(savedSensor); + + // Assert + Assertions.assertThat(updatedSensor).isNotNull(); + Assertions.assertThat(updatedSensor.getName()).isEqualTo(updatedName); + Assertions.assertThat(updatedSensor.getVersion()).isEqualTo(updatedSensorVersion); + Assertions.assertThat(updatedSensor.getData()).isEqualTo(updatedSensorData); + } +} \ No newline at end of file From f2979718e31bd7637f0beb5148c4a1dc2b12a997 Mon Sep 17 00:00:00 2001 From: Selahattin <98191442+SelahattinSert@users.noreply.github.com> Date: Sat, 4 Jan 2025 03:01:02 +0300 Subject: [PATCH 40/40] Add motion and temperature sensor service tests --- .../service/impl/MotionSensorServiceTest.java | 258 ++++++++++++++++++ .../impl/TemperatureSensorServiceTest.java | 258 ++++++++++++++++++ 2 files changed, 516 insertions(+) create mode 100644 src/test/java/com/onboarding/camera/cameraonboarding/service/impl/MotionSensorServiceTest.java create mode 100644 src/test/java/com/onboarding/camera/cameraonboarding/service/impl/TemperatureSensorServiceTest.java diff --git a/src/test/java/com/onboarding/camera/cameraonboarding/service/impl/MotionSensorServiceTest.java b/src/test/java/com/onboarding/camera/cameraonboarding/service/impl/MotionSensorServiceTest.java new file mode 100644 index 0000000..46eaa8e --- /dev/null +++ b/src/test/java/com/onboarding/camera/cameraonboarding/service/impl/MotionSensorServiceTest.java @@ -0,0 +1,258 @@ +package com.onboarding.camera.cameraonboarding.service.impl; + +import com.onboarding.camera.cameraonboarding.entity.Camera; +import com.onboarding.camera.cameraonboarding.entity.MotionSensor; +import com.onboarding.camera.cameraonboarding.enums.SensorType; +import com.onboarding.camera.cameraonboarding.exception.CameraNotFoundException; +import com.onboarding.camera.cameraonboarding.exception.SensorNotFoundException; +import com.onboarding.camera.cameraonboarding.exception.SensorNotUpdatedException; +import com.onboarding.camera.cameraonboarding.repository.MotionSensorRepository; +import com.onboarding.camera.cameraonboarding.service.CameraService; +import jakarta.transaction.Transactional; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@ExtendWith(MockitoExtension.class) +class MotionSensorServiceTest { + + @Mock + private MotionSensorRepository motionSensorRepository; + + @Mock + private CameraService cameraService; + + @Mock + private Camera camera; + + @InjectMocks + private MotionSensorService motionSensorService; + + private MotionSensor sensor; + + + private final UUID SENSOR_ID = UUID.randomUUID(); + private final String SENSOR_NAME = "Motion Sensor 1"; + private final SensorType SENSOR_TYPE = SensorType.MOTION; + private final UUID CAMERA_ID = UUID.randomUUID(); + private final UUID NON_EXISTING_CAM_ID = UUID.fromString("ef556dc0-0ddc-4f39-a96d-6886a54eee54"); + private final String UPDATED_SENSOR_NAME = "Updated Motion Sensor"; + private final String SENSOR_VERSION = "v1.0"; + private final String UPDATED_SENSOR_DATA = "Updated Sensor Data"; + + @BeforeEach + void setUp() { + sensor = new MotionSensor(); + sensor.setId(SENSOR_ID); + sensor.setName(SENSOR_NAME); + sensor.setSensorType(SENSOR_TYPE); + } + + @Test + @Transactional + void expect_handleCreateSensor_withValidSensor_returnSavedSensor() { + + // arrange + Mockito.when(motionSensorRepository.save(sensor)).thenReturn(sensor); + + // act + MotionSensor savedSensor = motionSensorService.handleCreateSensor(CAMERA_ID, sensor); + + // assert + Assertions.assertThat(savedSensor).isNotNull(); + Assertions.assertThat(savedSensor).isEqualTo(sensor); + Assertions.assertThat(savedSensor.getId()).isNotNull(); + Assertions.assertThat(savedSensor.getId()).isEqualTo(SENSOR_ID); + Assertions.assertThat(savedSensor.getName()).isNotNull(); + Assertions.assertThat(savedSensor.getName()).isEqualTo(SENSOR_NAME); + Assertions.assertThat(savedSensor.getSensorType()).isNotNull(); + Assertions.assertThat(savedSensor.getSensorType()).isEqualTo(SENSOR_TYPE); + + Mockito.verify(motionSensorRepository).save(sensor); + } + + @Test + void expect_handleCreateSensor_withNonExistingCamera_throwsCameraNotFoundException() { + + // arrange + camera.setCamId(NON_EXISTING_CAM_ID); + Mockito.when(motionSensorRepository.save(sensor)).thenThrow(new CameraNotFoundException("Camera not found, cameraId:" + NON_EXISTING_CAM_ID)); + + // act and assert + Assertions.assertThatThrownBy(() -> motionSensorService.handleCreateSensor(NON_EXISTING_CAM_ID, sensor)) + .isInstanceOf(CameraNotFoundException.class); + + Mockito.verify(motionSensorRepository).save(sensor); + } + + @Test + void expect_handleUpdateSensor_withValidData_returnsUpdatedSensor() { + // arrange + sensor.setCamera(camera); + sensor.setName(UPDATED_SENSOR_NAME); + sensor.setVersion(SENSOR_VERSION); + sensor.setData(UPDATED_SENSOR_DATA); + Mockito.when(cameraService.getCameraById(CAMERA_ID)).thenReturn(camera); + Mockito.when(motionSensorRepository.save(sensor)).thenReturn(sensor); + Mockito.when(camera.getSensors()).thenReturn(new ArrayList<>(List.of(sensor))); + + // act + MotionSensor updatedSensor = motionSensorService.handleUpdateSensor(CAMERA_ID, SENSOR_ID, sensor); + + // assert + Assertions.assertThat(updatedSensor).isNotNull(); + Assertions.assertThat(updatedSensor).isEqualTo(sensor); + Assertions.assertThat(updatedSensor.getName()).isNotNull(); + Assertions.assertThat(updatedSensor.getName()).isEqualTo(UPDATED_SENSOR_NAME); + Assertions.assertThat(updatedSensor.getVersion()).isNotNull(); + Assertions.assertThat(updatedSensor.getVersion()).isEqualTo(SENSOR_VERSION); + Assertions.assertThat(updatedSensor.getCamera()).isNotNull(); + Assertions.assertThat(updatedSensor.getCamera()).isEqualTo(camera); + Assertions.assertThat(updatedSensor.getData()).isNotNull(); + Assertions.assertThat(updatedSensor.getData()).isEqualTo(UPDATED_SENSOR_DATA); + + Mockito.verify(motionSensorRepository).save(sensor); + } + + @Test + void expect_handleUpdateSensor_withNonExistingSensor_throwsSensorNotFoundException() { + + // arrange + Mockito.when(cameraService.getCameraById(CAMERA_ID)).thenReturn(camera); + Mockito.when(camera.getSensors()).thenReturn(List.of()); + + // act and assert + Assertions.assertThatThrownBy(() -> motionSensorService.handleUpdateSensor(CAMERA_ID, SENSOR_ID, sensor)) + .isInstanceOf(SensorNotFoundException.class) + .hasMessageContaining("Sensor not found"); + + Mockito.verify(motionSensorRepository, Mockito.never()).save(Mockito.any()); + } + + @Test + void expect_handleUpdateSensor_withNonExistingCamera_throwsCameraNotFoundException() { + // arrange + Mockito.when(cameraService.getCameraById(CAMERA_ID)).thenThrow(new CameraNotFoundException("Camera not found, cameraId:" + CAMERA_ID)); + + // act and assert + Assertions.assertThatThrownBy(() -> motionSensorService.handleUpdateSensor(CAMERA_ID, SENSOR_ID, sensor)) + .isInstanceOf(CameraNotFoundException.class) + .hasMessageContaining("Camera not found"); + + Mockito.verify(motionSensorRepository, Mockito.never()).save(Mockito.any()); + } + + @Test + void expect_handleUpdateSensor_withRepositoryError_throwsSensorNotUpdatedException() { + + // arrange + Mockito.when(cameraService.getCameraById(CAMERA_ID)).thenReturn(camera); + Mockito.when(camera.getSensors()).thenReturn(new ArrayList<>(List.of(sensor))); + Mockito.when(motionSensorRepository.save(sensor)) + .thenThrow(new SensorNotUpdatedException("Error occurred while updating sensors")); + + // act and assert + Assertions.assertThatThrownBy(() -> motionSensorService.handleUpdateSensor(CAMERA_ID, SENSOR_ID, sensor)) + .isInstanceOf(SensorNotUpdatedException.class) + .hasMessageContaining("Error occurred while updating sensors"); + + Mockito.verify(motionSensorRepository).save(sensor); + } + + @Test + void expect_getSensorById_withValidSensorId_returnsSensor() { + + // arrange + Mockito.when(motionSensorRepository.findById(SENSOR_ID)).thenReturn(java.util.Optional.of(sensor)); + + // act + MotionSensor foundSensor = motionSensorService.getSensorById(SENSOR_ID); + + // assert + Assertions.assertThat(foundSensor).isEqualTo(sensor); + Mockito.verify(motionSensorRepository).findById(SENSOR_ID); + } + + @Test + void expect_getSensorById_withInvalidSensorId_throwsSensorNotFoundException() { + + // arrange + Mockito.when(motionSensorRepository.findById(SENSOR_ID)).thenReturn(java.util.Optional.empty()); + + // act and assert + Assertions.assertThatThrownBy(() -> motionSensorService.getSensorById(SENSOR_ID)) + .isInstanceOf(SensorNotFoundException.class); + + Mockito.verify(motionSensorRepository).findById(SENSOR_ID); + } + + @Test + void expect_handleDeleteSensor_withValidData_deletesSensor() { + + // arrange + Mockito.when(cameraService.getCameraById(CAMERA_ID)).thenReturn(camera); + Mockito.when(camera.getSensors()).thenReturn(new ArrayList<>(List.of(sensor))); + + // act + motionSensorService.handleDeleteSensor(CAMERA_ID, SENSOR_ID); + + // assert + Mockito.verify(motionSensorRepository).delete(sensor); + } + + @Test + void expect_handleDeleteSensor_withNonExistingSensor_throwsSensorNotFoundException() { + + // arrange + Mockito.when(cameraService.getCameraById(CAMERA_ID)).thenReturn(camera); + Mockito.when(camera.getSensors()).thenReturn(List.of()); + + // act and assert + Assertions.assertThatThrownBy(() -> motionSensorService.handleDeleteSensor(CAMERA_ID, SENSOR_ID)) + .isInstanceOf(SensorNotFoundException.class) + .hasMessageContaining("Sensor not found with id"); + + Mockito.verify(motionSensorRepository, Mockito.never()).delete(Mockito.any()); + } + + @Test + void expect_handleDeleteSensor_withNonExistingCamera_throwsCameraNotFoundException() { + + // arrange + Mockito.when(cameraService.getCameraById(CAMERA_ID)) + .thenThrow(new CameraNotFoundException("Camera not found, cameraId:" + CAMERA_ID)); + + // act and assert + Assertions.assertThatThrownBy(() -> motionSensorService.handleDeleteSensor(CAMERA_ID, SENSOR_ID)) + .isInstanceOf(CameraNotFoundException.class) + .hasMessageContaining("Camera not found, cameraId"); + + Mockito.verify(motionSensorRepository, Mockito.never()).delete(Mockito.any()); + } + + @Test + void expect_handleDeleteSensor_withRepositoryError_throwsSensorNotUpdatedException() { + + // arrange + Mockito.when(cameraService.getCameraById(CAMERA_ID)).thenReturn(camera); + Mockito.when(camera.getSensors()).thenReturn(new ArrayList<>(List.of(sensor))); + Mockito.doThrow(new RuntimeException("Error occurred while deleting sensor")) + .when(motionSensorRepository).delete(sensor); + + // act and assert + Assertions.assertThatThrownBy(() -> motionSensorService.handleDeleteSensor(CAMERA_ID, SENSOR_ID)) + .isInstanceOf(SensorNotUpdatedException.class) + .hasMessageContaining("Error occurred while deleting sensor"); + + Mockito.verify(motionSensorRepository).delete(sensor); + } +} \ No newline at end of file diff --git a/src/test/java/com/onboarding/camera/cameraonboarding/service/impl/TemperatureSensorServiceTest.java b/src/test/java/com/onboarding/camera/cameraonboarding/service/impl/TemperatureSensorServiceTest.java new file mode 100644 index 0000000..dea4b04 --- /dev/null +++ b/src/test/java/com/onboarding/camera/cameraonboarding/service/impl/TemperatureSensorServiceTest.java @@ -0,0 +1,258 @@ +package com.onboarding.camera.cameraonboarding.service.impl; + +import com.onboarding.camera.cameraonboarding.entity.Camera; +import com.onboarding.camera.cameraonboarding.entity.TemperatureSensor; +import com.onboarding.camera.cameraonboarding.enums.SensorType; +import com.onboarding.camera.cameraonboarding.exception.CameraNotFoundException; +import com.onboarding.camera.cameraonboarding.exception.SensorNotFoundException; +import com.onboarding.camera.cameraonboarding.exception.SensorNotUpdatedException; +import com.onboarding.camera.cameraonboarding.repository.TemperatureSensorRepository; +import com.onboarding.camera.cameraonboarding.service.CameraService; +import jakarta.transaction.Transactional; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@ExtendWith(MockitoExtension.class) +class TemperatureSensorServiceTest { + + @Mock + private TemperatureSensorRepository temperatureSensorRepository; + + @Mock + private CameraService cameraService; + + @Mock + private Camera camera; + + @InjectMocks + private TemperatureSensorService temperatureSensorService; + + private TemperatureSensor sensor; + + + private final UUID SENSOR_ID = UUID.randomUUID(); + private final String SENSOR_NAME = "Temperature Sensor 1"; + private final SensorType SENSOR_TYPE = SensorType.TEMPERATURE; + private final UUID CAMERA_ID = UUID.randomUUID(); + private final UUID NON_EXISTING_CAM_ID = UUID.fromString("ef556dc0-0ddc-4f39-a96d-6886a54eee54"); + private final String UPDATED_SENSOR_NAME = "Updated Temperature Sensor"; + private final String SENSOR_VERSION = "v1.0"; + private final String UPDATED_SENSOR_DATA = "Updated Sensor Data"; + + @BeforeEach + void setUp() { + sensor = new TemperatureSensor(); + sensor.setId(SENSOR_ID); + sensor.setName(SENSOR_NAME); + sensor.setSensorType(SENSOR_TYPE); + } + + @Test + @Transactional + void expect_handleCreateSensor_withValidSensor_returnSavedSensor() { + + // arrange + Mockito.when(temperatureSensorRepository.save(sensor)).thenReturn(sensor); + + // act + TemperatureSensor savedSensor = temperatureSensorService.handleCreateSensor(CAMERA_ID, sensor); + + // assert + Assertions.assertThat(savedSensor).isNotNull(); + Assertions.assertThat(savedSensor).isEqualTo(sensor); + Assertions.assertThat(savedSensor.getId()).isNotNull(); + Assertions.assertThat(savedSensor.getId()).isEqualTo(SENSOR_ID); + Assertions.assertThat(savedSensor.getName()).isNotNull(); + Assertions.assertThat(savedSensor.getName()).isEqualTo(SENSOR_NAME); + Assertions.assertThat(savedSensor.getSensorType()).isNotNull(); + Assertions.assertThat(savedSensor.getSensorType()).isEqualTo(SENSOR_TYPE); + + Mockito.verify(temperatureSensorRepository).save(sensor); + } + + @Test + void expect_handleCreateSensor_withNonExistingCamera_throwsCameraNotFoundException() { + + // arrange + camera.setCamId(NON_EXISTING_CAM_ID); + Mockito.when(temperatureSensorRepository.save(sensor)).thenThrow(new CameraNotFoundException("Camera not found, cameraId:" + NON_EXISTING_CAM_ID)); + + // act and assert + Assertions.assertThatThrownBy(() -> temperatureSensorService.handleCreateSensor(NON_EXISTING_CAM_ID, sensor)) + .isInstanceOf(CameraNotFoundException.class); + + Mockito.verify(temperatureSensorRepository).save(sensor); + } + + @Test + void expect_handleUpdateSensor_withValidData_returnsUpdatedSensor() { + // arrange + sensor.setCamera(camera); + sensor.setName(UPDATED_SENSOR_NAME); + sensor.setVersion(SENSOR_VERSION); + sensor.setData(UPDATED_SENSOR_DATA); + Mockito.when(cameraService.getCameraById(CAMERA_ID)).thenReturn(camera); + Mockito.when(temperatureSensorRepository.save(sensor)).thenReturn(sensor); + Mockito.when(camera.getSensors()).thenReturn(new ArrayList<>(List.of(sensor))); + + // act + TemperatureSensor updatedSensor = temperatureSensorService.handleUpdateSensor(CAMERA_ID, SENSOR_ID, sensor); + + // assert + Assertions.assertThat(updatedSensor).isNotNull(); + Assertions.assertThat(updatedSensor).isEqualTo(sensor); + Assertions.assertThat(updatedSensor.getName()).isNotNull(); + Assertions.assertThat(updatedSensor.getName()).isEqualTo(UPDATED_SENSOR_NAME); + Assertions.assertThat(updatedSensor.getVersion()).isNotNull(); + Assertions.assertThat(updatedSensor.getVersion()).isEqualTo(SENSOR_VERSION); + Assertions.assertThat(updatedSensor.getCamera()).isNotNull(); + Assertions.assertThat(updatedSensor.getCamera()).isEqualTo(camera); + Assertions.assertThat(updatedSensor.getData()).isNotNull(); + Assertions.assertThat(updatedSensor.getData()).isEqualTo(UPDATED_SENSOR_DATA); + + Mockito.verify(temperatureSensorRepository).save(sensor); + } + + @Test + void expect_handleUpdateSensor_withNonExistingSensor_throwsSensorNotFoundException() { + + // arrange + Mockito.when(cameraService.getCameraById(CAMERA_ID)).thenReturn(camera); + Mockito.when(camera.getSensors()).thenReturn(List.of()); + + // act and assert + Assertions.assertThatThrownBy(() -> temperatureSensorService.handleUpdateSensor(CAMERA_ID, SENSOR_ID, sensor)) + .isInstanceOf(SensorNotFoundException.class) + .hasMessageContaining("Sensor not found"); + + Mockito.verify(temperatureSensorRepository, Mockito.never()).save(Mockito.any()); + } + + @Test + void expect_handleUpdateSensor_withNonExistingCamera_throwsCameraNotFoundException() { + // arrange + Mockito.when(cameraService.getCameraById(CAMERA_ID)).thenThrow(new CameraNotFoundException("Camera not found, cameraId:" + CAMERA_ID)); + + // act and assert + Assertions.assertThatThrownBy(() -> temperatureSensorService.handleUpdateSensor(CAMERA_ID, SENSOR_ID, sensor)) + .isInstanceOf(CameraNotFoundException.class) + .hasMessageContaining("Camera not found"); + + Mockito.verify(temperatureSensorRepository, Mockito.never()).save(Mockito.any()); + } + + @Test + void expect_handleUpdateSensor_withRepositoryError_throwsSensorNotUpdatedException() { + + // arrange + Mockito.when(cameraService.getCameraById(CAMERA_ID)).thenReturn(camera); + Mockito.when(camera.getSensors()).thenReturn(new ArrayList<>(List.of(sensor))); + Mockito.when(temperatureSensorRepository.save(sensor)) + .thenThrow(new SensorNotUpdatedException("Error occurred while updating sensors")); + + // act and assert + Assertions.assertThatThrownBy(() -> temperatureSensorService.handleUpdateSensor(CAMERA_ID, SENSOR_ID, sensor)) + .isInstanceOf(SensorNotUpdatedException.class) + .hasMessageContaining("Error occurred while updating sensors"); + + Mockito.verify(temperatureSensorRepository).save(sensor); + } + + @Test + void expect_getSensorById_withValidSensorId_returnsSensor() { + + // arrange + Mockito.when(temperatureSensorRepository.findById(SENSOR_ID)).thenReturn(java.util.Optional.of(sensor)); + + // act + TemperatureSensor foundSensor = temperatureSensorService.getSensorById(SENSOR_ID); + + // assert + Assertions.assertThat(foundSensor).isEqualTo(sensor); + Mockito.verify(temperatureSensorRepository).findById(SENSOR_ID); + } + + @Test + void expect_getSensorById_withInvalidSensorId_throwsSensorNotFoundException() { + + // arrange + Mockito.when(temperatureSensorRepository.findById(SENSOR_ID)).thenReturn(java.util.Optional.empty()); + + // act and assert + Assertions.assertThatThrownBy(() -> temperatureSensorService.getSensorById(SENSOR_ID)) + .isInstanceOf(SensorNotFoundException.class); + + Mockito.verify(temperatureSensorRepository).findById(SENSOR_ID); + } + + @Test + void expect_handleDeleteSensor_withValidData_deletesSensor() { + + // arrange + Mockito.when(cameraService.getCameraById(CAMERA_ID)).thenReturn(camera); + Mockito.when(camera.getSensors()).thenReturn(new ArrayList<>(List.of(sensor))); + + // act + temperatureSensorService.handleDeleteSensor(CAMERA_ID, SENSOR_ID); + + // assert + Mockito.verify(temperatureSensorRepository).delete(sensor); + } + + @Test + void expect_handleDeleteSensor_withNonExistingSensor_throwsSensorNotFoundException() { + + // arrange + Mockito.when(cameraService.getCameraById(CAMERA_ID)).thenReturn(camera); + Mockito.when(camera.getSensors()).thenReturn(List.of()); + + // act and assert + Assertions.assertThatThrownBy(() -> temperatureSensorService.handleDeleteSensor(CAMERA_ID, SENSOR_ID)) + .isInstanceOf(SensorNotFoundException.class) + .hasMessageContaining("Sensor not found with id"); + + Mockito.verify(temperatureSensorRepository, Mockito.never()).delete(Mockito.any()); + } + + @Test + void expect_handleDeleteSensor_withNonExistingCamera_throwsCameraNotFoundException() { + + // arrange + Mockito.when(cameraService.getCameraById(CAMERA_ID)) + .thenThrow(new CameraNotFoundException("Camera not found, cameraId:" + CAMERA_ID)); + + // act and assert + Assertions.assertThatThrownBy(() -> temperatureSensorService.handleDeleteSensor(CAMERA_ID, SENSOR_ID)) + .isInstanceOf(CameraNotFoundException.class) + .hasMessageContaining("Camera not found, cameraId"); + + Mockito.verify(temperatureSensorRepository, Mockito.never()).delete(Mockito.any()); + } + + @Test + void expect_handleDeleteSensor_withRepositoryError_throwsSensorNotUpdatedException() { + + // arrange + Mockito.when(cameraService.getCameraById(CAMERA_ID)).thenReturn(camera); + Mockito.when(camera.getSensors()).thenReturn(new ArrayList<>(List.of(sensor))); + Mockito.doThrow(new RuntimeException("Error occurred while deleting sensor")) + .when(temperatureSensorRepository).delete(sensor); + + // act and assert + Assertions.assertThatThrownBy(() -> temperatureSensorService.handleDeleteSensor(CAMERA_ID, SENSOR_ID)) + .isInstanceOf(SensorNotUpdatedException.class) + .hasMessageContaining("Error occurred while deleting sensor"); + + Mockito.verify(temperatureSensorRepository).delete(sensor); + } +} \ No newline at end of file