diff --git a/src/main/java/org/unilab/uniplan/major/MajorController.java b/src/main/java/org/unilab/uniplan/major/MajorController.java index d3a16543..4bc35b5b 100644 --- a/src/main/java/org/unilab/uniplan/major/MajorController.java +++ b/src/main/java/org/unilab/uniplan/major/MajorController.java @@ -17,7 +17,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.unilab.uniplan.major.dto.MajorCoursesResponseDto; -import org.unilab.uniplan.major.dto.MajorDto; import org.unilab.uniplan.major.dto.MajorRequestDto; import org.unilab.uniplan.major.dto.MajorResponseDto; @@ -27,52 +26,51 @@ @Tag(name = "Majors", description = "Manage academic majors (e.g., Informatics, Software Engineering) associated with faculties") public class MajorController { - private final MajorService majorService; - private final MajorMapper majorMapper; + private final MajorWebFacade majorWebFacade; @PostMapping - public ResponseEntity addMajor(@RequestBody @NotNull + public ResponseEntity createMajor(@RequestBody @NotNull @Valid final MajorRequestDto majorRequestDTO) { - final MajorDto majorDTO = majorMapper.toInnerDto(majorRequestDTO); - return ResponseEntity.status(HttpStatus.CREATED) - .body(majorMapper.toResponseDto(majorService.createMajor(majorDTO))); + majorWebFacade.createMajor(majorRequestDTO); + + return ResponseEntity.status(HttpStatus.CREATED).build(); } @GetMapping("/{id}") public ResponseEntity getMajorById(@PathVariable final UUID id) { - return ResponseEntity.ok(majorMapper.toResponseDto(majorService.findMajorById(id))); + return ResponseEntity.ok(majorWebFacade.getMajorById(id)); } @GetMapping("/{id}/courses") public ResponseEntity getMajorWithCoursesById(@PathVariable final UUID id) { - return ResponseEntity.ok(majorMapper.toFullResponseDto(majorService.findMajorWithCoursesById(id))); + return ResponseEntity.ok(majorWebFacade.getMajorWithCoursesById(id)); } @GetMapping("/faculty/{facultyId}") - public List getMajorsByFacultyId(@PathVariable final UUID facultyId) { - return majorMapper.toResponseDtoList(majorService.findAllMajorByFacultyId(facultyId)); + public ResponseEntity> getMajorsByFacultyId(@PathVariable final UUID facultyId) { + return ResponseEntity.ok(majorWebFacade.getMajorsByFacultyId(facultyId)); } @GetMapping("/faculty/{facultyId}/courses") - public List getMajorsWithCoursesByFacultyId(@PathVariable final UUID facultyId) { - return majorMapper.toFullResponseDtoList(majorService.findAllMajorWithCoursesByFacultyId(facultyId)); + public ResponseEntity> getMajorsWithCoursesByFacultyId(@PathVariable final UUID facultyId) { + return ResponseEntity.ok(majorWebFacade.getMajorsWithCoursesByFacultyId(facultyId)); } @GetMapping - public List getAllMajors() { - return majorMapper.toResponseDtoList(majorService.findAll()); + public ResponseEntity> getAllMajors() { + return ResponseEntity.ok(majorWebFacade.getAllMajors()); } @PutMapping("/{id}") - public ResponseEntity updateMajor(@PathVariable final UUID id, + public ResponseEntity updateMajor(@PathVariable final UUID id, @RequestBody @NotNull @Valid MajorRequestDto majorRequestDTO) { - final MajorDto majorDTO = majorMapper.toInnerDto(majorRequestDTO); - return ResponseEntity.ok(majorMapper.toResponseDto(majorService.updateMajor(id, majorDTO))); + majorWebFacade.updateMajor(id, majorRequestDTO); + return ResponseEntity.noContent().build(); } @DeleteMapping("/{id}") public ResponseEntity deleteMajor(@PathVariable final UUID id) { - majorService.deleteMajor(id); + majorWebFacade.deleteMajor(id); return ResponseEntity.noContent().build(); } } \ No newline at end of file diff --git a/src/main/java/org/unilab/uniplan/major/MajorMapper.java b/src/main/java/org/unilab/uniplan/major/MajorMapper.java index 782457ac..3330c563 100644 --- a/src/main/java/org/unilab/uniplan/major/MajorMapper.java +++ b/src/main/java/org/unilab/uniplan/major/MajorMapper.java @@ -7,7 +7,6 @@ import org.unilab.uniplan.course.CourseMapper; import org.unilab.uniplan.major.dto.MajorCoursesDto; import org.unilab.uniplan.major.dto.MajorCoursesResponseDto; -import org.unilab.uniplan.major.dto.MajorDto; import org.unilab.uniplan.major.dto.MajorRequestDto; import org.unilab.uniplan.major.dto.MajorResponseDto; @@ -15,25 +14,18 @@ public interface MajorMapper { @Mapping(source = "facultyId", target = "faculty.id") - Major toEntity(MajorDto majorDto); - - @Mapping(source = "faculty.id", target = "facultyId") - MajorDto toDto(Major major); - - @Mapping(source = "faculty.id", target = "facultyId") - MajorCoursesDto toFullDto(Major major); + Major toEntity(MajorRequestDto majorRequestDto); @Mapping(source = "facultyId", target = "faculty.id") - void updateEntityFromDto(MajorDto majorDto, @MappingTarget Major major); + void updateEntityFromDto(MajorRequestDto majorRequestDto, @MappingTarget Major major); - @Mapping(target = "id", ignore = true) - MajorDto toInnerDto(MajorRequestDto requestDto); - - MajorResponseDto toResponseDto(MajorDto innerDto); + @Mapping(source = "faculty.id", target = "facultyId") + MajorResponseDto toResponseDto(Major major); - List toResponseDtoList(List majors); + List toResponseDtoList(List majors); - MajorCoursesResponseDto toFullResponseDto(MajorCoursesDto innerDto); + @Mapping(source = "faculty.id", target = "facultyId") + MajorCoursesResponseDto toFullResponseDto(Major major); - List toFullResponseDtoList(List majors); + List toFullResponseDtoList(List majors); } \ No newline at end of file diff --git a/src/main/java/org/unilab/uniplan/major/MajorRepository.java b/src/main/java/org/unilab/uniplan/major/MajorRepository.java index b32c9c81..9306d4e0 100644 --- a/src/main/java/org/unilab/uniplan/major/MajorRepository.java +++ b/src/main/java/org/unilab/uniplan/major/MajorRepository.java @@ -4,10 +4,10 @@ import java.util.UUID; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; -import org.unilab.uniplan.faculty.Faculty; @Repository public interface MajorRepository extends JpaRepository { List findAllByFacultyId(UUID facultyId); + List findAllMajorWithCoursesByFacultyId(UUID facultyId); } diff --git a/src/main/java/org/unilab/uniplan/major/MajorService.java b/src/main/java/org/unilab/uniplan/major/MajorService.java index 0933024b..9e9f0672 100644 --- a/src/main/java/org/unilab/uniplan/major/MajorService.java +++ b/src/main/java/org/unilab/uniplan/major/MajorService.java @@ -1,88 +1,43 @@ package org.unilab.uniplan.major; -import org.unilab.uniplan.major.dto.MajorCoursesDto; - -import static org.unilab.uniplan.utils.ErrorConstants.MAJOR_NOT_FOUND; - -import jakarta.transaction.Transactional; +import org.unilab.uniplan.common.model.BaseService; import java.util.List; +import java.util.Optional; import java.util.UUID; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; -import org.unilab.uniplan.exception.ResourceNotFoundException; -import org.unilab.uniplan.major.dto.MajorDto; @Service @RequiredArgsConstructor -public class MajorService { +public class MajorService implements BaseService { private final MajorRepository majorRepository; - private final MajorMapper majorMapper; - - @Transactional - public MajorDto createMajor(final MajorDto majorDTO) { - final Major major = majorMapper.toEntity(majorDTO); - return saveEntityAndConvertToDto(major); - } - - public MajorDto findMajorById(final UUID id) { - return majorRepository.findById(id) - .map(majorMapper::toDto) - .orElseThrow(() -> new ResourceNotFoundException( - MAJOR_NOT_FOUND.getMessage(String.valueOf(id)))); - } - - public MajorCoursesDto findMajorWithCoursesById(final UUID id) { - return majorRepository.findById(id) - .map(majorMapper::toFullDto) - .orElseThrow(() -> new ResourceNotFoundException( - MAJOR_NOT_FOUND.getMessage(String.valueOf(id)))); - } - - public List findAll() { - return majorRepository.findAll() - .stream().map(majorMapper::toDto).toList(); - } - public List findAllMajorByFacultyId(final UUID facultyId) { - return majorRepository.findAllByFacultyId(facultyId) - .stream() - .map(majorMapper::toDto) - .toList(); + @Override + public void save(final Major major) { + majorRepository.save(major); } - public List findAllMajorWithCoursesByFacultyId(final UUID facultyId) { - return majorRepository.findAllByFacultyId(facultyId) - .stream() - .map(majorMapper::toFullDto) - .toList(); + @Override + public Optional getById(final UUID id) { + return majorRepository.findById(id); } - @Transactional - public MajorDto updateMajor(final UUID id, final MajorDto majorDTO) { - return majorRepository.findById(id).map(existingMajor -> updateEntityAndConvertToDto( - majorDTO, - existingMajor)) - .orElseThrow(() -> new ResourceNotFoundException(MAJOR_NOT_FOUND.getMessage( - String.valueOf(id)))); + @Override + public List getAll() { + return majorRepository.findAll(); } - @Transactional - public void deleteMajor(final UUID id) { - final Major major = majorRepository.findById(id) - .orElseThrow(() -> new ResourceNotFoundException( - MAJOR_NOT_FOUND.getMessage(String.valueOf(id)))); + @Override + public void delete(final Major major) { majorRepository.delete(major); } - private MajorDto updateEntityAndConvertToDto(final MajorDto dto, - final Major entity) { - majorMapper.updateEntityFromDto(dto, entity); - return saveEntityAndConvertToDto(entity); + public List findAllMajorByFacultyId(final UUID facultyId) { + return majorRepository.findAllByFacultyId(facultyId); } - private MajorDto saveEntityAndConvertToDto(final Major entity) { - final Major savedEntity = majorRepository.save(entity); - return majorMapper.toDto(savedEntity); + public List findAllMajorWithCoursesByFacultyId(final UUID facultyId) { + return majorRepository.findAllMajorWithCoursesByFacultyId(facultyId); } } diff --git a/src/main/java/org/unilab/uniplan/major/MajorValidator.java b/src/main/java/org/unilab/uniplan/major/MajorValidator.java new file mode 100644 index 00000000..3c5d5ae0 --- /dev/null +++ b/src/main/java/org/unilab/uniplan/major/MajorValidator.java @@ -0,0 +1,29 @@ +package org.unilab.uniplan.major; + +import static org.unilab.uniplan.utils.ErrorConstants.FACULTY_NOT_FOUND; + +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.unilab.uniplan.exception.ResourceNotFoundException; +import org.unilab.uniplan.faculty.FacultyRepository; +import org.unilab.uniplan.major.dto.MajorRequestDto; + +@Component +@RequiredArgsConstructor +public class MajorValidator { + + private final FacultyRepository facultyRepository; + + public void validate(final MajorRequestDto requestDto) { + validateFacultyExists(requestDto.facultyId()); + } + + private void validateFacultyExists(final UUID facultyId) { + if (!facultyRepository.existsById(facultyId)) { + throw new ResourceNotFoundException( + FACULTY_NOT_FOUND.getMessage(String.valueOf(facultyId)) + ); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/unilab/uniplan/major/MajorWebFacade.java b/src/main/java/org/unilab/uniplan/major/MajorWebFacade.java new file mode 100644 index 00000000..6d44a982 --- /dev/null +++ b/src/main/java/org/unilab/uniplan/major/MajorWebFacade.java @@ -0,0 +1,95 @@ +package org.unilab.uniplan.major; + +import static org.unilab.uniplan.utils.ErrorConstants.MAJOR_NOT_FOUND; + +import java.util.List; +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; +import org.unilab.uniplan.exception.ResourceNotFoundException; +import org.unilab.uniplan.major.dto.MajorCoursesResponseDto; +import org.unilab.uniplan.major.dto.MajorRequestDto; +import org.unilab.uniplan.major.dto.MajorResponseDto; + +@Component +@Slf4j +@RequiredArgsConstructor +public class MajorWebFacade { + + private final MajorService majorService; + private final MajorMapper majorMapper; + private final MajorValidator majorValidator; + + @Transactional + public void createMajor(final MajorRequestDto requestDto) { + majorValidator.validate(requestDto); + + final Major major = majorMapper.toEntity(requestDto); + majorService.save(major); + + log.info("Created major with ID: {}", major.getId()); + } + + @Transactional(readOnly = true) + public List getAllMajors() { + return majorMapper.toResponseDtoList(majorService.getAll()); + } + + @Transactional(readOnly = true) + public MajorResponseDto getMajorById(final UUID id) { + final Major major = getMajorOrThrow(id); + + return majorMapper.toResponseDto(major); + } + + @Transactional + public void updateMajor(final UUID id, + final MajorRequestDto requestDto) { + majorValidator.validate(requestDto); + + final Major major = getMajorOrThrow(id); + majorMapper.updateEntityFromDto(requestDto, major); + majorService.save(major); + + log.info("Updated major with ID: {}", id); + } + + @Transactional + public void deleteMajor(final UUID id) { + final Major major = getMajorOrThrow(id); + + majorService.delete(major); + + log.info("Deleted major with ID: {}", id); + } + + private Major getMajorOrThrow(final UUID id) { + return majorService.getById(id) + .orElseThrow(() -> new ResourceNotFoundException( + MAJOR_NOT_FOUND.getMessage(String.valueOf(id)) + )); + } + + @Transactional(readOnly = true) + public MajorCoursesResponseDto getMajorWithCoursesById(final UUID id) { + final Major major = getMajorOrThrow(id); + + return majorMapper.toFullResponseDto(major); + } + + @Transactional(readOnly = true) + public List getMajorsByFacultyId(final UUID facultyId) { + return majorMapper.toResponseDtoList( + majorService.findAllMajorByFacultyId(facultyId) + ); + } + + @Transactional(readOnly = true) + public List getMajorsWithCoursesByFacultyId(final UUID facultyId) { + return majorMapper.toFullResponseDtoList( + majorService.findAllMajorWithCoursesByFacultyId(facultyId) + ); + } +} \ No newline at end of file diff --git a/src/main/java/org/unilab/uniplan/major/dto/MajorRequestDto.java b/src/main/java/org/unilab/uniplan/major/dto/MajorRequestDto.java index 632bf969..a69956d9 100644 --- a/src/main/java/org/unilab/uniplan/major/dto/MajorRequestDto.java +++ b/src/main/java/org/unilab/uniplan/major/dto/MajorRequestDto.java @@ -1,14 +1,15 @@ package org.unilab.uniplan.major.dto; +import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; import java.util.UUID; public record MajorRequestDto( - @NotNull + @NotNull(message = "Faculty id cannot be null") UUID facultyId, - @NotNull - @Size(max = 200) + @NotBlank(message = "Major is required") + @Size(max = 200, message = "Major name must be at most 200 characters") String majorName ) { diff --git a/src/main/java/org/unilab/uniplan/major/dto/MajorResponseDto.java b/src/main/java/org/unilab/uniplan/major/dto/MajorResponseDto.java index d8233618..1ec656b2 100644 --- a/src/main/java/org/unilab/uniplan/major/dto/MajorResponseDto.java +++ b/src/main/java/org/unilab/uniplan/major/dto/MajorResponseDto.java @@ -1,15 +1,10 @@ package org.unilab.uniplan.major.dto; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; import java.util.UUID; public record MajorResponseDto( UUID id, - @NotNull UUID facultyId, - @NotNull - @Size(max = 200) String majorName ) { diff --git a/src/test/java/org/unilab/uniplan/major/MajorServiceTest.java b/src/test/java/org/unilab/uniplan/major/MajorServiceTest.java index 6430ee97..34c3f6c2 100644 --- a/src/test/java/org/unilab/uniplan/major/MajorServiceTest.java +++ b/src/test/java/org/unilab/uniplan/major/MajorServiceTest.java @@ -1,13 +1,7 @@ package org.unilab.uniplan.major; -import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.List; @@ -19,24 +13,16 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.unilab.uniplan.exception.ResourceNotFoundException; -import org.unilab.uniplan.major.dto.MajorCoursesDto; -import org.unilab.uniplan.major.dto.MajorDto; @ExtendWith(MockitoExtension.class) class MajorServiceTest { - @InjectMocks - private MajorService majorService; - @Mock private MajorRepository majorRepository; - @Mock - private MajorMapper majorMapper; + @InjectMocks + private MajorService majorService; - private MajorCoursesDto majorCoursesDto; - private MajorDto majorDTO; private Major major; private UUID majorId; private UUID facultyId; @@ -45,35 +31,26 @@ class MajorServiceTest { void setUp() { majorId = UUID.randomUUID(); facultyId = UUID.randomUUID(); - majorCoursesDto = new MajorCoursesDto(majorId, facultyId, "Informatics", List.of()); - majorDTO = new MajorDto(majorId, facultyId, "Informatics"); major = new Major(); } @Test - void createMajorShouldReturnAndSavedMajorDTO() { - when(majorMapper.toEntity(majorDTO)).thenReturn(major); - when(majorRepository.save(major)).thenReturn(major); - when(majorMapper.toDto(major)).thenReturn(majorDTO); + void saveShouldSaveMajor() { + majorService.save(major); - MajorDto result = majorService.createMajor(majorDTO); - - assertNotNull(result); - assertEquals("Informatics", result.majorName()); - assertEquals(facultyId, result.facultyId()); verify(majorRepository).save(major); } @Test void findAllMajorByFacultyIdShouldReturnListOfMajors() { + final List majors = List.of(major); + when(majorRepository.findAllByFacultyId(facultyId)).thenReturn(List.of(major)); - when(majorMapper.toDto(major)).thenReturn(majorDTO); - List result = majorService.findAllMajorByFacultyId(facultyId); + final List result = majorService.findAllMajorByFacultyId(facultyId); - assertNotNull(result); - assertEquals(1, result.size()); - assertEquals("Informatics", result.getFirst().majorName()); + assertEquals(majors, result); + verify(majorRepository).findAllByFacultyId(facultyId); } @Test @@ -87,143 +64,61 @@ void findAllMajorByFacultyIdShouldReturnEmptyList() { } @Test - void findAllMajorWithCoursesByFacultyIdShouldReturnListOfMajorCoursesDto() { - when(majorRepository.findAllByFacultyId(facultyId)).thenReturn(List.of(major)); - when(majorMapper.toFullDto(major)).thenReturn(majorCoursesDto); - - final List result = majorService.findAllMajorWithCoursesByFacultyId(facultyId); - - assertAll( - () -> assertNotNull(result), - () -> assertEquals(1, result.size()), - () -> assertEquals("Informatics", result.getFirst().majorName()), - () -> assertEquals(List.of(), result.getFirst().courses()) - ); - } - - @Test - void findAllMajorWithCoursesByFacultyIdShouldReturnEmptyList() { - when(majorRepository.findAllByFacultyId(facultyId)).thenReturn(List.of()); - - assertTrue(majorService.findAllMajorWithCoursesByFacultyId(facultyId).isEmpty()); - - verify(majorRepository).findAllByFacultyId(facultyId); - } - - @Test - void findMajorByIdShouldReturnMajorDTOIfFound() { - when(majorRepository.findById(majorId)).thenReturn(Optional.of(major)); - when(majorMapper.toDto(major)).thenReturn(majorDTO); - - MajorDto result = majorService.findMajorById(majorId); - - assertEquals("Informatics", result.majorName()); - } - - @Test - void findMajorByIdShouldReturnEmptyIfNotFound() { - when(majorRepository.findById(majorId)).thenReturn(Optional.empty()); - - ResourceNotFoundException exception = assertThrows(ResourceNotFoundException.class, () -> majorService.findMajorById(majorId)); - - assertTrue(exception.getMessage().contains(String.valueOf(majorId))); - } - - @Test - void findMajorWithCoursesByIdShouldReturnMajorCoursesDtoIfFound() { + void getByIdShouldReturnMajorOptionalIfMajorExists() { when(majorRepository.findById(majorId)).thenReturn(Optional.of(major)); - when(majorMapper.toFullDto(major)).thenReturn(majorCoursesDto); - final MajorCoursesDto result = majorService.findMajorWithCoursesById(majorId); + Optional result = majorService.getById(majorId); - assertAll( - () -> assertNotNull(result), - () -> assertEquals("Informatics", result.majorName()), - () -> assertEquals(List.of(), result.courses()) - ); + assertEquals(Optional.of(major), result); + verify(majorRepository).findById(majorId); } @Test - void findMajorWithCoursesByIdShouldReturnEmptyIfNotFound() { + void getByIdShouldReturnEmptyOptionalIfMajorDoesNotExist() { when(majorRepository.findById(majorId)).thenReturn(Optional.empty()); - ResourceNotFoundException exception = assertThrows(ResourceNotFoundException.class, () -> majorService.findMajorWithCoursesById(majorId)); + final Optional result = majorService.getById(majorId); - assertTrue(exception.getMessage().contains(String.valueOf(majorId))); + assertEquals(Optional.empty(), result); + verify(majorRepository).findById(majorId); } @Test - void findAllShouldReturnListOfMajorDTOs() { + void getAllShouldReturnListOfMajors() { + final List majors = List.of(major); when(majorRepository.findAll()).thenReturn(List.of(major)); - when(majorMapper.toDto(major)).thenReturn(majorDTO); - - List result = majorService.findAll(); - - assertEquals(1, result.size()); - assertEquals("Informatics", result.getFirst().majorName()); - } - - @Test - void updateMajorShouldReturnUpdatedMajorDTOIfFound() { - when(majorRepository.findById(majorId)).thenReturn(Optional.of(major)); - doNothing().when(majorMapper).updateEntityFromDto(majorDTO, major); - when(majorRepository.save(major)).thenReturn(major); - when(majorMapper.toDto(major)).thenReturn(majorDTO); - - MajorDto result = majorService.updateMajor(majorId, majorDTO); - - assertEquals("Informatics", result.majorName()); - verify(majorRepository).save(major); - } - - @Test - void updateMajorShouldReturnEmptyIfNotFound() { - when(majorRepository.findById(majorId)).thenReturn(Optional.empty()); - ResourceNotFoundException exception = assertThrows(ResourceNotFoundException.class, () -> majorService.updateMajor(majorId, majorDTO)); + final List result = majorService.getAll(); - assertTrue(exception.getMessage().contains(String.valueOf(majorId))); - verify(majorRepository, never()).save(any()); + assertEquals(majors, result); + verify(majorRepository).findAll(); } @Test - void deleteMajorShouldDeleteIfExists() { - when(majorRepository.findById(majorId)).thenReturn(Optional.of(major)); - - majorService.deleteMajor(majorId); + void deleteShouldDeleteMajor() { + majorService.delete(major); verify(majorRepository).delete(major); } @Test - void deleteMajorShouldThrowIfNotExists() { - when(majorRepository.findById(majorId)).thenReturn(Optional.empty()); + void findAllMajorWithCoursesByFacultyIdShouldReturnListOfMajors() { + final List majors = List.of(major); - ResourceNotFoundException exception = assertThrows(ResourceNotFoundException.class, - () -> majorService.deleteMajor(majorId)); + when(majorRepository.findAllMajorWithCoursesByFacultyId(facultyId)).thenReturn(List.of(major)); - assertTrue(exception.getMessage().contains("Major with ID")); - verify(majorRepository, never()).delete(any()); - } + final List result = majorService.findAllMajorWithCoursesByFacultyId(facultyId); - @Test - void findByIdShouldReturnEntityIfExists() { - when(majorRepository.findById(majorId)).thenReturn(Optional.of(major)); - when(majorMapper.toDto(major)).thenReturn(majorDTO); - - MajorDto result = majorService.findMajorById(majorId); - - assertEquals(majorDTO, result); - verify(majorMapper).toDto(major); + assertEquals(majors, result); + verify(majorRepository).findAllMajorWithCoursesByFacultyId(facultyId); } @Test - void findByIdShouldReturnEmptyIfNotFound() { - when(majorRepository.findById(majorId)).thenReturn(Optional.empty()); + void findAllMajorWithCoursesByFacultyIdShouldReturnEmptyList() { + when(majorRepository.findAllMajorWithCoursesByFacultyId(facultyId)).thenReturn(List.of()); - org.unilab.uniplan.exception.ResourceNotFoundException exception = assertThrows( - ResourceNotFoundException.class, () -> majorService.findMajorById(majorId)); + assertTrue(majorService.findAllMajorWithCoursesByFacultyId(facultyId).isEmpty()); - assertTrue(exception.getMessage().contains(String.valueOf(majorId))); + verify(majorRepository).findAllMajorWithCoursesByFacultyId(facultyId); } } diff --git a/src/test/java/org/unilab/uniplan/major/MajorValidatorTest.java b/src/test/java/org/unilab/uniplan/major/MajorValidatorTest.java new file mode 100644 index 00000000..64c9088b --- /dev/null +++ b/src/test/java/org/unilab/uniplan/major/MajorValidatorTest.java @@ -0,0 +1,58 @@ +package org.unilab.uniplan.major; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.UUID; +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.junit.jupiter.MockitoExtension; +import org.unilab.uniplan.exception.ResourceNotFoundException; +import org.unilab.uniplan.faculty.FacultyRepository; +import org.unilab.uniplan.major.dto.MajorRequestDto; + +@ExtendWith(MockitoExtension.class) +class MajorValidatorTest { + + @Mock + private FacultyRepository facultyRepository; + + @InjectMocks + private MajorValidator majorValidator; + + private UUID facultyId; + private MajorRequestDto requestDto; + + @BeforeEach + void setUp() { + facultyId = UUID.randomUUID(); + requestDto = mock(MajorRequestDto.class); + + when(requestDto.facultyId()).thenReturn(facultyId); + } + + @Test + void validate_shouldPass_whenFacultyExists() { + when(facultyRepository.existsById(facultyId)).thenReturn(true); + + assertDoesNotThrow(() -> majorValidator.validate(requestDto)); + + verify(facultyRepository).existsById(facultyId); + } + + @Test + void validate_shouldThrow_whenFacultyDoesNotExist() { + when(facultyRepository.existsById(facultyId)).thenReturn(false); + + assertThrows(ResourceNotFoundException.class, + () -> majorValidator.validate(requestDto)); + + verify(facultyRepository).existsById(facultyId); + } +} \ No newline at end of file diff --git a/src/test/java/org/unilab/uniplan/major/MajorWebFacadeTest.java b/src/test/java/org/unilab/uniplan/major/MajorWebFacadeTest.java new file mode 100644 index 00000000..516f1dc2 --- /dev/null +++ b/src/test/java/org/unilab/uniplan/major/MajorWebFacadeTest.java @@ -0,0 +1,209 @@ +package org.unilab.uniplan.major; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InOrder; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.unilab.uniplan.exception.ResourceNotFoundException; +import org.unilab.uniplan.major.dto.MajorCoursesResponseDto; +import org.unilab.uniplan.major.dto.MajorRequestDto; +import org.unilab.uniplan.major.dto.MajorResponseDto; + +@ExtendWith(MockitoExtension.class) +class MajorWebFacadeTest { + + @Mock + private MajorService majorService; + + @Mock + private MajorMapper majorMapper; + + @Mock + private MajorValidator majorValidator; + + @InjectMocks + private MajorWebFacade majorWebFacade; + + private UUID majorId; + private UUID facultyId; + private Major major; + private MajorRequestDto requestDto; + private MajorResponseDto responseDto; + private MajorCoursesResponseDto coursesResponseDto; + + @BeforeEach + void setUp() { + majorId = UUID.randomUUID(); + facultyId = UUID.randomUUID(); + major = new Major(); + requestDto = mock(MajorRequestDto.class); + responseDto = mock(MajorResponseDto.class); + coursesResponseDto = mock(MajorCoursesResponseDto.class); + } + + @Test + void createMajorShouldValidateMapAndSaveMajor() { + when(majorMapper.toEntity(requestDto)).thenReturn(major); + + majorWebFacade.createMajor(requestDto); + + final InOrder inOrder = inOrder(majorValidator, majorMapper, majorService); + inOrder.verify(majorValidator).validate(requestDto); + inOrder.verify(majorMapper).toEntity(requestDto); + inOrder.verify(majorService).save(major); + } + + @Test + void getAllMajorsShouldReturnResponseDtoList() { + final List majors = List.of(major); + final List responseDtos = List.of(responseDto); + + when(majorService.getAll()).thenReturn(majors); + when(majorMapper.toResponseDtoList(majors)).thenReturn(responseDtos); + + final List result = majorWebFacade.getAllMajors(); + + assertEquals(responseDtos, result); + verify(majorService).getAll(); + verify(majorMapper).toResponseDtoList(majors); + } + + @Test + void getMajorByIdShouldReturnResponseDtoIfFound() { + when(majorService.getById(majorId)).thenReturn(Optional.of(major)); + when(majorMapper.toResponseDto(major)).thenReturn(responseDto); + + final MajorResponseDto result = majorWebFacade.getMajorById(majorId); + + assertEquals(responseDto, result); + verify(majorService).getById(majorId); + verify(majorMapper).toResponseDto(major); + } + + @Test + void getMajorByIdShouldThrowIfMajorDoesNotExist() { + when(majorService.getById(majorId)).thenReturn(Optional.empty()); + + assertThrows(ResourceNotFoundException.class, + () -> majorWebFacade.getMajorById(majorId)); + + verify(majorService).getById(majorId); + verify(majorMapper, never()).toResponseDto(any(Major.class)); + } + + @Test + void getMajorWithCoursesByIdShouldReturnCoursesResponseDtoIfFound() { + when(majorService.getById(majorId)).thenReturn(Optional.of(major)); + when(majorMapper.toFullResponseDto(major)).thenReturn(coursesResponseDto); + + final MajorCoursesResponseDto result = majorWebFacade.getMajorWithCoursesById(majorId); + + assertEquals(coursesResponseDto, result); + verify(majorService).getById(majorId); + verify(majorMapper).toFullResponseDto(major); + } + + @Test + void getMajorWithCoursesByIdShouldThrowIfMajorDoesNotExist() { + when(majorService.getById(majorId)).thenReturn(Optional.empty()); + + assertThrows(ResourceNotFoundException.class, + () -> majorWebFacade.getMajorWithCoursesById(majorId)); + + verify(majorService).getById(majorId); + verify(majorMapper, never()).toFullResponseDto(any(Major.class)); + } + + @Test + void getMajorsByFacultyIdShouldReturnResponseDtoList() { + final List majors = List.of(major); + final List responseDtos = List.of(responseDto); + + when(majorService.findAllMajorByFacultyId(facultyId)).thenReturn(majors); + when(majorMapper.toResponseDtoList(majors)).thenReturn(responseDtos); + + final List result = majorWebFacade.getMajorsByFacultyId(facultyId); + + assertEquals(responseDtos, result); + verify(majorService).findAllMajorByFacultyId(facultyId); + verify(majorMapper).toResponseDtoList(majors); + } + + @Test + void getMajorsWithCoursesByFacultyIdShouldReturnCoursesResponseDtoList() { + final List majors = List.of(major); + final List responseDtos = List.of(coursesResponseDto); + + when(majorService.findAllMajorWithCoursesByFacultyId(facultyId)).thenReturn(majors); + when(majorMapper.toFullResponseDtoList(majors)).thenReturn(responseDtos); + + final List result = + majorWebFacade.getMajorsWithCoursesByFacultyId(facultyId); + + assertEquals(responseDtos, result); + verify(majorService).findAllMajorWithCoursesByFacultyId(facultyId); + verify(majorMapper).toFullResponseDtoList(majors); + } + + @Test + void updateMajorShouldValidateUpdateMapAndSaveMajorIfFound() { + when(majorService.getById(majorId)).thenReturn(Optional.of(major)); + + majorWebFacade.updateMajor(majorId, requestDto); + + final InOrder inOrder = inOrder(majorValidator, majorService, majorMapper); + inOrder.verify(majorValidator).validate(requestDto); + inOrder.verify(majorService).getById(majorId); + inOrder.verify(majorMapper).updateEntityFromDto(requestDto, major); + inOrder.verify(majorService).save(major); + } + + @Test + void updateMajorShouldThrowIfMajorDoesNotExist() { + when(majorService.getById(majorId)).thenReturn(Optional.empty()); + + assertThrows(ResourceNotFoundException.class, + () -> majorWebFacade.updateMajor(majorId, requestDto)); + + verify(majorValidator).validate(requestDto); + verify(majorService).getById(majorId); + verify(majorMapper, never()).updateEntityFromDto(any(MajorRequestDto.class), any(Major.class)); + verify(majorService, never()).save(any(Major.class)); + } + + @Test + void deleteMajorShouldDeleteMajorIfFound() { + when(majorService.getById(majorId)).thenReturn(Optional.of(major)); + + majorWebFacade.deleteMajor(majorId); + + verify(majorService).getById(majorId); + verify(majorService).delete(major); + } + + @Test + void deleteMajorShouldThrowIfMajorDoesNotExist() { + when(majorService.getById(majorId)).thenReturn(Optional.empty()); + + assertThrows(ResourceNotFoundException.class, + () -> majorWebFacade.deleteMajor(majorId)); + + verify(majorService).getById(majorId); + verify(majorService, never()).delete(any(Major.class)); + } +} \ No newline at end of file