diff --git a/core/src/main/java/cz/muni/fi/pa165/core/device/DeviceRepository.java b/core/src/main/java/cz/muni/fi/pa165/core/device/DeviceRepository.java index 70d7a39a95db52b89dc53d39029ce0a74e2d70e5..ec4712a84ffc7cff2c578776ad52b896521b790a 100644 --- a/core/src/main/java/cz/muni/fi/pa165/core/device/DeviceRepository.java +++ b/core/src/main/java/cz/muni/fi/pa165/core/device/DeviceRepository.java @@ -1,9 +1,13 @@ package cz.muni.fi.pa165.core.device; +import cz.muni.fi.pa165.core.company.Company; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import java.util.Optional; @Repository -public interface DeviceRepository extends JpaRepository<Device, String> {} +public interface DeviceRepository extends JpaRepository<Device, String> { + Optional<Device> findByName(String name); + +} diff --git a/core/src/main/java/cz/muni/fi/pa165/core/device/DeviceService.java b/core/src/main/java/cz/muni/fi/pa165/core/device/DeviceService.java index 98a7c27e4b48de06a7824ba64f30ec0ce524034c..06df84d2b9ab798a5311233103d5377792c0108d 100644 --- a/core/src/main/java/cz/muni/fi/pa165/core/device/DeviceService.java +++ b/core/src/main/java/cz/muni/fi/pa165/core/device/DeviceService.java @@ -1,9 +1,11 @@ package cz.muni.fi.pa165.core.device; import cz.muni.fi.pa165.core.common.DomainService; +import cz.muni.fi.pa165.core.company.Company; import lombok.Getter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service @@ -15,4 +17,12 @@ public class DeviceService extends DomainService<Device> { public DeviceService(DeviceRepository deviceRepository) { repository = deviceRepository; } + + @Transactional(readOnly = true) + public Device findByName(String name) { + return getRepository() + .findByName(name) + .filter(entity -> entity.getDeletedDateTime() == null) + .orElse(null); + } } diff --git a/core/src/test/java/cz/muni/fi/pa165/core/device/DeviceServiceTest.java b/core/src/test/java/cz/muni/fi/pa165/core/device/DeviceServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..061694aaa3defa78a1dc40e73a8ebbc5296db4b4 --- /dev/null +++ b/core/src/test/java/cz/muni/fi/pa165/core/device/DeviceServiceTest.java @@ -0,0 +1,282 @@ +package cz.muni.fi.pa165.core.device; + +import cz.muni.fi.pa165.core.company.Company; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; + +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.openMocks; + +/** + * DeviceService unit tests + * + * @author xskacel + */ + +public class DeviceServiceTest { + + @InjectMocks + private DeviceService deviceService; + + @Mock + private DeviceRepository deviceRepositoryMock; + + @BeforeEach + void init() { + openMocks(this); + } + + @Test + void shouldGetDeviceById() { + Company company = Company.builder().name("Apple").build(); + + Device device = Device + .builder() + .company(company) + .name("device-1") + .build(); + + when(deviceRepositoryMock.findById(device.getId())).thenReturn(Optional.of(device)); + + Device result = deviceService.findById(device.getId()); + + verify(deviceRepositoryMock).findById(device.getId()); + + assertEquals(device, result); + } + + @Test + void shouldCreateNewDevice() { + Company company = Company.builder().name("Apple").build(); + + Device device = Device + .builder() + .company(company) + .name("device-1") + .build(); + + when(deviceRepositoryMock.save(device)).thenReturn(device); + + Device createdDevice = deviceService.create(device); + + verify(deviceRepositoryMock).save(device); + + assertThat(createdDevice).isEqualTo(device); + } + + @Test + void shouldFindDeviceByName() { + Company company = Company.builder().name("Apple").build(); + + Device device = Device + .builder() + .company(company) + .name("device-1") + .build(); + + when(deviceRepositoryMock.findByName(device.getName())).thenReturn(Optional.of(device)); + + Device result = deviceService.findByName(device.getName()); + + verify(deviceRepositoryMock).findByName(device.getName()); + + assertEquals(device, result); + } + + @Test + void shouldFindAllDevicePageableInt() { + Company company = Company.builder().name("Apple").build(); + + Device firstDevice = Device.builder() + .name("Bohemia") + .company(company) + .build(); + + Device secondDevice = Device.builder() + .name("New Company") + .company(company) + .build(); + + Page<Device> page = new PageImpl<>(List.of(firstDevice, secondDevice)); + + int pageNumber = 0; + int pageSize = 10; + + when(deviceRepositoryMock.findAll(PageRequest.of(pageNumber, pageSize))).thenReturn(page); + + Page<Device> result = deviceService.findAllPageableInt(pageNumber); + + verify(deviceRepositoryMock).findAll(PageRequest.of(pageNumber, pageSize)); + + assertThat(result).containsExactlyInAnyOrder(firstDevice, secondDevice); + } + + @Test + void shouldDeleteDeviceById() { + Company company = Company.builder().name("Apple").build(); + + Device device = Device.builder() + .name("Bohemia") + .company(company) + .build(); + + when(deviceRepositoryMock.findById(device.getId())).thenReturn(Optional.of(device)); + + Device deletedDevice = deviceService.deleteById(device.getId()); + + verify(deviceRepositoryMock).findById(device.getId()); + verify(deviceRepositoryMock).save(device); // soft delete + + assertNotNull(deletedDevice.getDeletedDateTime()); + assertEquals(device, deletedDevice); + } + + @Test + void shouldUpdateDevice() { + Company firstCompany = Company.builder().name("Apple").build(); + Company secondCompany = Company.builder().name("New Company").build(); + + Device originalDevice = Device.builder() + .name("Bohemia") + .company(firstCompany) + .build(); + + Device updatedDevice = Device.builder() + .name("New Device") + .company(secondCompany) + .build(); + + when(deviceRepositoryMock.findById(originalDevice.getId())).thenReturn(Optional.of(originalDevice)); + + when(deviceRepositoryMock.save(updatedDevice)).thenReturn(updatedDevice); + + Device result = deviceService.update(updatedDevice, originalDevice.getId()); + + verify(deviceRepositoryMock).findById(originalDevice.getId()); + verify(deviceRepositoryMock).save(updatedDevice); + + assertEquals(originalDevice.getId(), result.getId()); + assertEquals(updatedDevice.getName(), result.getName()); + assertEquals(updatedDevice.getCompany().getName(), result.getCompany().getName()); + } + + @Test + void shouldHardDeleteAllDevices() { + deviceService.hardDeleteAll(); + verify(deviceRepositoryMock).deleteAll(); + } + + @Test + void shouldDeleteAllDevices() { + var data = List.of( + Device.builder().name("Bohemia").company(Company.builder().name("Apple").build()).build(), + Device.builder().name("Slovakia").company(Company.builder().name("Mac").build()).build() + ); + when(deviceRepositoryMock.findAll()).thenReturn(data); + deviceService.deleteAll(); + verify(deviceRepositoryMock).findAll(); + verify(deviceRepositoryMock).saveAll(data); + } + + @Test + void shouldDeleteAllDevicesIds() { + Device firstDevice = Device + .builder() + .name("Bohemia") + .company(Company + .builder() + .name("Apple") + .build()) + .build(); + + Device secondDevice = Device + .builder() + .name("Slovakia") + .company(Company + .builder() + .name("Mac") + .build()) + .build(); + + String[] ids = {firstDevice.getId(), secondDevice.getId()}; + when(deviceRepositoryMock.findById(ids[0])).thenReturn(Optional.of(firstDevice)); + when(deviceRepositoryMock.findById(ids[1])).thenReturn(Optional.of(secondDevice)); + + deviceService.deleteAllById(ids); + + verify(deviceRepositoryMock).save(firstDevice); + verify(deviceRepositoryMock).save(secondDevice); + } + + @Test + void shouldFindAllDevices() { + var data = List.of( + Device.builder().name("Bohemia").company(Company.builder().name("Apple").build()).build(), + Device.builder().name("Slovakia").company(Company.builder().name("Mac").build()).build() + ); + + when(deviceRepositoryMock.findAll()).thenReturn(data); + List<Device> result = deviceService.findAll(); + verify(deviceRepositoryMock).findAll(); + assertEquals(data, result); + } + + @Test + void shouldFindAllDevicesPageable() { + int pageNumber = 0; + int pageSize = 10; + Pageable pageable = PageRequest.of(pageNumber, pageSize); + + var data = List.of( + Device.builder().name("Bohemia").company(Company.builder().name("Apple").build()).build(), + Device.builder().name("Slovakia").company(Company.builder().name("Mac").build()).build() + ); + + Page<Device> pageResult = new PageImpl<>(data, pageable, data.size()); + when(deviceRepositoryMock.findAll(pageable)).thenReturn(pageResult); + + Page<Device> result = deviceService.findAllPageable(pageable); + verify(deviceRepositoryMock).findAll(pageable); + + assertEquals(pageResult, result); + } + // TODO: Do constraint checking for softdelete (non-cascade) + /* + // because of FK constraint on SmartMeter + @Test + void shouldNotAllowDeleteDeviceById() { + SmartMeter smartMeter = SmartMeter + .builder() + .name("my-smart-device-1") + .build(); + Device device = Device + .builder() + .name("device-with-smart-meter") + .company(Company + .builder() + .name("Apple") + .build() + ).smartMeterList( + List.of(smartMeter) + ).build(); + smartMeter.setDevice(device); + + when(deviceRepositoryMock.findById(device.getId())).thenReturn(Optional.of(device)); + + assertThrows(DataIntegrityViolationException.class, () -> deviceService.deleteById(device.getId())); + } + */ +}