diff --git a/application/model/src/main/java/org/fuseri/model/dto/common/DomainObjectDto.java b/application/model/src/main/java/org/fuseri/model/dto/common/DomainObjectDto.java index 7824c73ce2a163dd543b3dd4f17b70d44fb3e74a..0956e176bd13d3cdbdb66ac3b59c36d109a94afe 100644 --- a/application/model/src/main/java/org/fuseri/model/dto/common/DomainObjectDto.java +++ b/application/model/src/main/java/org/fuseri/model/dto/common/DomainObjectDto.java @@ -1,11 +1,13 @@ package org.fuseri.model.dto.common; import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; @Getter @Setter +@EqualsAndHashCode(exclude = "id") public abstract class DomainObjectDto { @NotNull diff --git a/application/model/src/main/java/org/fuseri/model/dto/course/CourseCreateDto.java b/application/model/src/main/java/org/fuseri/model/dto/course/CourseCreateDto.java index 64c78eec16aa0a472883f9b1d705d8168d523b8f..2ba3673e96f42b9b3b14fdb6406faed1030268ac 100644 --- a/application/model/src/main/java/org/fuseri/model/dto/course/CourseCreateDto.java +++ b/application/model/src/main/java/org/fuseri/model/dto/course/CourseCreateDto.java @@ -6,6 +6,7 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; @@ -16,6 +17,7 @@ import lombok.Setter; @Getter @Setter @AllArgsConstructor +@EqualsAndHashCode(callSuper = false) public class CourseCreateDto { @NotBlank(message = "Course name is required") diff --git a/application/model/src/main/java/org/fuseri/model/dto/course/CourseDto.java b/application/model/src/main/java/org/fuseri/model/dto/course/CourseDto.java index 18e5695b056c1f3f477a05c5abd8f83bba32c9a1..e0d571ff570d9845cfda18b31862473816d3b748 100644 --- a/application/model/src/main/java/org/fuseri/model/dto/course/CourseDto.java +++ b/application/model/src/main/java/org/fuseri/model/dto/course/CourseDto.java @@ -20,7 +20,7 @@ import java.util.List; */ @Getter @Setter -@EqualsAndHashCode(callSuper = true) +@EqualsAndHashCode(callSuper = false) public class CourseDto extends DomainObjectDto { @NotBlank(message = "Course name is required") @@ -43,12 +43,13 @@ public class CourseDto extends DomainObjectDto { @Valid private List<Long> studentIds; - public CourseDto(Long id, String name, Integer capacity, LanguageTypeDto languageTypeDto, ProficiencyLevelDto proficiencyLevelDto) { - this.setId(id); + + public CourseDto(String name, Integer capacity, LanguageTypeDto languageTypeDto, ProficiencyLevelDto proficiencyLevelDto) { this.name = name; this.capacity = capacity; this.language = languageTypeDto; this.proficiency = proficiencyLevelDto; this.studentIds = new ArrayList<>(); } + } diff --git a/application/model/src/main/java/org/fuseri/model/dto/lecture/LectureCreateDto.java b/application/model/src/main/java/org/fuseri/model/dto/lecture/LectureCreateDto.java index 0279180b41ea671a944ab270735ac5f5c00acb75..b7ec0926fd958f722109fcf52421f4c47934f8b4 100644 --- a/application/model/src/main/java/org/fuseri/model/dto/lecture/LectureCreateDto.java +++ b/application/model/src/main/java/org/fuseri/model/dto/lecture/LectureCreateDto.java @@ -12,11 +12,11 @@ public class LectureCreateDto { @Future(message = "Lecture start date and time must be in the future") @NotNull(message = "Lecture start date and time cannot be null") - private LocalDateTime from; + private LocalDateTime lectureFrom; @Future(message = "Lecture end date and time must be in the future") @NotNull(message = "Lecture end date and time cannot be null") - private LocalDateTime to; + private LocalDateTime lectureTo; @NotBlank(message = "Lecture topic cannot be blank") @Size(max = 255, message = "Lecture topic must be no more than {max} characters") @@ -30,8 +30,8 @@ public class LectureCreateDto { private Long courseId; public LectureCreateDto(LocalDateTime from, LocalDateTime to, String topic, Integer capacity, Long courseId) { - this.from = from; - this.to = to; + this.lectureFrom = from; + this.lectureTo = to; this.topic = topic; this.capacity = capacity; this.courseId = courseId; @@ -39,7 +39,7 @@ public class LectureCreateDto { @AssertTrue(message = "Lecture start datetime must be before Lecture end datetime") private boolean isFromDateBeforeToDate() { - if (from == null || to == null) return true; - return from.isBefore(to); + if (lectureFrom == null || lectureTo == null) return true; + return lectureFrom.isBefore(lectureTo); } } diff --git a/application/model/src/main/java/org/fuseri/model/dto/lecture/LectureDto.java b/application/model/src/main/java/org/fuseri/model/dto/lecture/LectureDto.java index df35d83cfa5668cb6c9d28b514d50221f6425584..73820adce9c8b5281064b96c6c0811253488b63c 100644 --- a/application/model/src/main/java/org/fuseri/model/dto/lecture/LectureDto.java +++ b/application/model/src/main/java/org/fuseri/model/dto/lecture/LectureDto.java @@ -1,25 +1,26 @@ package org.fuseri.model.dto.lecture; import jakarta.validation.constraints.*; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; import org.fuseri.model.dto.common.DomainObjectDto; import java.time.LocalDateTime; -import java.util.ArrayList; import java.util.List; @Getter @Setter +@EqualsAndHashCode(callSuper = false) public class LectureDto extends DomainObjectDto { @Future(message = "Lecture start date and time must be in the future") @NotNull(message = "Lecture start date and time cannot be null") - private LocalDateTime from; + private LocalDateTime lectureFrom; @Future(message = "Lecture end date and time must be in the future") @NotNull(message = "Lecture end date and time cannot be null") - private LocalDateTime to; + private LocalDateTime lectureTo; @NotBlank(message = "Lecture topic cannot be blank") @Size(max = 255, message = "Lecture topic must be no more than {max} characters") @@ -36,21 +37,21 @@ public class LectureDto extends DomainObjectDto { private Long courseId; @NotNull(message = "Student IDs list cannot be null") - private List<Long> studentIds; + private List<Long> students; - public LectureDto(LocalDateTime from, LocalDateTime to, String topic, Integer capacity, Long lecturerId, Long courseId) { - this.from = from; - this.to = to; + public LectureDto(LocalDateTime from, LocalDateTime to, String topic, Integer capacity, Long lecturerId, Long courseId, List<Long> students) { + this.lectureFrom = from; + this.lectureTo = to; this.topic = topic; this.capacity = capacity; this.lecturerId = lecturerId; this.courseId = courseId; - this.studentIds = new ArrayList<>(); + this.students = students; } @AssertTrue(message = "Lecture start datetime must be before Lecture end datetime") private boolean isFromDateBeforeToDate() { - if (from == null || to == null) return true; - return from.isBefore(to); + if (lectureFrom == null || lectureTo == null) return true; + return lectureFrom.isBefore(lectureTo); } } diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/common/DomainObject.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/common/DomainObject.java index 078871d947aaa180bd7a5f6549354cadd7b2eade..a4ef86b4c2474a672041b2e05a4c875c9152fe29 100644 --- a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/common/DomainObject.java +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/common/DomainObject.java @@ -4,11 +4,13 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.MappedSuperclass; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; @Getter @Setter +@EqualsAndHashCode(exclude = "id") @MappedSuperclass public abstract class DomainObject { diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/Course.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/Course.java index 99e1ff83bc6f5d1ffcaffcd2689327a4e29e1ff9..2ebc62497878b82eed5dcb9a53d597fd82076050 100644 --- a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/Course.java +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/Course.java @@ -6,7 +6,6 @@ import org.fuseri.modulelanguageschool.common.DomainObject; import org.fuseri.modulelanguageschool.user.User; import java.util.List; -import java.util.Set; @Getter @Setter @@ -14,6 +13,7 @@ import java.util.Set; @Table(name = "course") @NoArgsConstructor @AllArgsConstructor +@EqualsAndHashCode(callSuper = false) public class Course extends DomainObject { private String name; @@ -26,7 +26,7 @@ public class Course extends DomainObject { private ProficiencyLevel proficiency; @ManyToMany - private Set<User> students; + private List<User> students; public void enrolStudent(User student) { students.add(student); diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseController.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseController.java index 353dcd43d30b280c8cf683fe794faeb0c29d01b9..1e2bbac5e0f6e4d9a4752e9a0afc83a5c4adb5b7 100644 --- a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseController.java +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseController.java @@ -2,6 +2,8 @@ package org.fuseri.modulelanguageschool.course; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; import jakarta.validation.Valid; import org.fuseri.model.dto.course.CourseCreateDto; import org.fuseri.model.dto.course.CourseDto; @@ -12,6 +14,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -40,8 +44,13 @@ public class CourseController { */ @ApiOperation(value = "Create a new course") @PostMapping - public CourseDto create(@Valid @RequestBody CourseCreateDto dto) { - return courseFacade.create(dto); + @ApiResponses({ + @ApiResponse(code = 201, message = "Course created successfully"), + @ApiResponse(code = 400, message = "Invalid request body") + }) + public ResponseEntity<CourseDto> create(@Valid @RequestBody CourseCreateDto dto) { + CourseDto courseDto = courseFacade.create(dto); + return ResponseEntity.status(HttpStatus.CREATED).body(courseDto); } /** @@ -52,8 +61,13 @@ public class CourseController { */ @ApiOperation(value = "Retrieve a course by ID") @GetMapping("/find/{id}") - public CourseDto find(@PathVariable Long id) { - return courseFacade.findById(id); + @ApiResponses({ + @ApiResponse(code = 200, message = "Course found"), + @ApiResponse(code = 404, message = "Course not found") + }) + public ResponseEntity<CourseDto> find(@PathVariable Long id) { + CourseDto courseDto = courseFacade.findById(id); + return ResponseEntity.ok(courseDto); } /** @@ -64,8 +78,13 @@ public class CourseController { */ @ApiOperation(value = "Retrieve a paginated list of courses") @GetMapping("/findAll") - public Page<CourseDto> findAll(@RequestParam int page) { - return courseFacade.findAll(PageRequest.of(page, 10, Sort.by(Sort.Direction.ASC, "name"))); + @ApiResponses(value = { + @ApiResponse(code = 200, message = "Successfully retrieved courses"), + @ApiResponse(code = 404, message = "No courses found") + }) + public ResponseEntity<Page<CourseDto>> findAll(@RequestParam int page) { + Page<CourseDto> courseDtoPage = courseFacade.findAll(PageRequest.of(page, 10, Sort.by(Sort.Direction.ASC, "name"))); + return ResponseEntity.ok(courseDtoPage); } /** @@ -76,10 +95,14 @@ public class CourseController { */ @ApiOperation(value = "Retrieve a paginated list of courses of a given language") @GetMapping("/findAllByLang") - public List<CourseDto> findAll(@RequestParam LanguageTypeDto lang) { - return courseFacade.findAll(lang); + @ApiResponses({ + @ApiResponse(code = 200, message = "Courses found"), + @ApiResponse(code = 400, message = "Invalid request body") + }) + public ResponseEntity<List<CourseDto>> findAll(@RequestParam LanguageTypeDto lang) { + List<CourseDto> courseDtos = courseFacade.findAll(lang); + return ResponseEntity.ok(courseDtos); } - /** * Retrieves a paginated list of courses of a given language and proficiency * @@ -89,9 +112,14 @@ public class CourseController { */ @ApiOperation(value = "Retrieve a paginated list of courses of a given language and proficiency") @GetMapping("/findAllByLangProf") - public List<CourseDto> findAll(@RequestParam LanguageTypeDto lang, + @ApiResponses({ + @ApiResponse(code = 200, message = "Courses found"), + @ApiResponse(code = 400, message = "Invalid request body") + }) + public ResponseEntity<List<CourseDto>> findAll(@RequestParam LanguageTypeDto lang, @RequestParam ProficiencyLevelDto prof) { - return courseFacade.findAll(lang, prof); + List<CourseDto> courses = courseFacade.findAll(lang, prof); + return ResponseEntity.ok(courses); } /** @@ -103,8 +131,14 @@ public class CourseController { */ @ApiOperation(value = "Update an existing course") @PutMapping("/update/{id}") - public CourseDto update(@PathVariable Long id, @Valid @RequestBody CourseCreateDto dto) { - return courseFacade.update(id, dto); + @ApiResponses({ + @ApiResponse(code = 200, message = "Course updated successfully"), + @ApiResponse(code = 400, message = "Invalid request body"), + @ApiResponse(code = 404, message = "Course not found") + }) + public ResponseEntity<CourseDto> update(@PathVariable Long id, @Valid @RequestBody CourseCreateDto dto) { + CourseDto updatedCourse = courseFacade.update(id, dto); + return ResponseEntity.ok(updatedCourse); } /** @@ -114,11 +148,15 @@ public class CourseController { */ @ApiOperation(value = "Delete a course by ID") @DeleteMapping("/delete/{id}") - public void delete(@PathVariable Long id) { + @ApiResponses({ + @ApiResponse(code = 204, message = "Course deleted successfully"), + @ApiResponse(code = 404, message = "Course not found") + }) + public ResponseEntity<Void> delete(@PathVariable Long id) { courseFacade.delete(id); + return ResponseEntity.noContent().build(); } - /** * Adds student to the existing course * @@ -128,8 +166,13 @@ public class CourseController { */ @ApiOperation(value = "Add student to the existing course") @PatchMapping("/enrol/{id}") - public CourseDto enrol(@PathVariable Long id, @RequestBody UserDto student) { - return courseFacade.enrol(id, student); + @ApiResponses(value = { + @ApiResponse(code = 200, message = "Successfully enrolled student in course"), + @ApiResponse(code = 404, message = "Course not found") + }) + public ResponseEntity<CourseDto> enrol(@PathVariable Long id, @RequestBody UserDto student) { + CourseDto updatedCourse = courseFacade.enrol(id, student); + return ResponseEntity.ok(updatedCourse); } /** @@ -141,8 +184,13 @@ public class CourseController { */ @ApiOperation(value = "Remove student from the existing course") @PatchMapping("/expel/{id}") - public CourseDto expel(@PathVariable Long id, @RequestBody UserDto student) { - return courseFacade.expel(id, student); + @ApiResponses(value = { + @ApiResponse(code = 200, message = "Successfully expelled student from course"), + @ApiResponse(code = 404, message = "Course not found") + }) + public ResponseEntity<CourseDto> expel(@PathVariable Long id, @RequestBody UserDto student) { + CourseDto updatedCourse = courseFacade.expel(id, student); + return ResponseEntity.ok(updatedCourse); } } diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseFacade.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseFacade.java index db7f28aac1051afbb68b097701e87d5b7cd916d5..47c060452ee71a0188ca36ff8f0e5609f0285976 100644 --- a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseFacade.java +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseFacade.java @@ -18,16 +18,22 @@ import java.util.List; @Service @Transactional public class CourseFacade { - private final CourseService courseService; - private final CourseMapper courseMapper; - private final UserMapper userMapper; @Autowired - public CourseFacade(CourseService courseService, CourseMapper courseMapper, UserMapper userMapper) { - this.courseService = courseService; - this.courseMapper = courseMapper; - this.userMapper = userMapper; - } + private CourseService courseService; + + @Autowired + private CourseMapper courseMapper; + + @Autowired + private UserMapper userMapper; + +// @Autowired +// public CourseFacade(CourseService courseService, CourseMapper courseMapper, UserMapper userMapper) { +// this.courseService = courseService; +// this.courseMapper = courseMapper; +// this.userMapper = userMapper; +// } @Transactional public CourseDto create(CourseCreateDto dto) { diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseService.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseService.java index 13079299f90503bc9f66ca889e05cd59ae6473f0..4e54b9f91bba5849884d37e2ac291c8dd9ee000b 100644 --- a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseService.java +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseService.java @@ -1,12 +1,13 @@ package org.fuseri.modulelanguageschool.course; -import org.fuseri.modulelanguageschool.common.ResourceNotFoundException; import org.fuseri.modulelanguageschool.user.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.server.ResponseStatusException; import java.util.List; import java.util.Optional; @@ -29,7 +30,8 @@ public class CourseService { @Transactional(readOnly = true) public Course findById(Long id) { return courseRepository.findById(id) - .orElseThrow(() -> new ResourceNotFoundException("Course with id: " + id + " was not found.")); + .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, + "Course with id: " + id + " was not found.")); } @Transactional(readOnly = true) @@ -48,7 +50,8 @@ public class CourseService { course.setProficiency(newCourse.getProficiency()); return courseRepository.save(course); } else { - throw new ResourceNotFoundException("Course with id: " + id + " was not found."); + throw new ResponseStatusException(HttpStatus.NOT_FOUND, + "Course with id: " + id + " was not found."); } } @@ -72,7 +75,8 @@ public class CourseService { course.enrolStudent(student); return courseRepository.save(course); } else { - throw new ResourceNotFoundException("Course with id: " + id + " was not found."); + throw new ResponseStatusException(HttpStatus.NOT_FOUND, + "Course with id: " + id + " was not found."); } } @@ -83,7 +87,8 @@ public class CourseService { course.expelStudent(student); return courseRepository.save(course); } else { - throw new ResourceNotFoundException("Course with id: " + id + " was not found."); + throw new ResponseStatusException(HttpStatus.NOT_FOUND, + "Course with id: " + id + " was not found."); } } } diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/lecture/Lecture.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/lecture/Lecture.java index a719f242bad99bdd3349d44cdddbbc51fc2319fa..14afc0a256929f0c98f8ad3aa461896488d95189 100644 --- a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/lecture/Lecture.java +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/lecture/Lecture.java @@ -4,16 +4,13 @@ import jakarta.persistence.Entity; import jakarta.persistence.ManyToMany; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; +import lombok.*; import org.fuseri.modulelanguageschool.common.DomainObject; import org.fuseri.modulelanguageschool.course.Course; import org.fuseri.modulelanguageschool.user.User; import java.time.LocalDateTime; -import java.util.Set; +import java.util.List; /** * This class represents a lecture entity in the domain model. @@ -24,11 +21,13 @@ import java.util.Set; @Table(name = "lecture") @NoArgsConstructor @AllArgsConstructor +@EqualsAndHashCode(callSuper = false) public class Lecture extends DomainObject { - private LocalDateTime from; - private LocalDateTime to; + private LocalDateTime lectureFrom; + private LocalDateTime lectureTo; private String topic; + private Integer capacity; @ManyToOne private Course course; @@ -37,7 +36,7 @@ public class Lecture extends DomainObject { private User lecturer; @ManyToMany - private Set<User> students; + private List<User> students; public void enrolStudent(User student) { students.add(student); diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/lecture/LectureController.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/lecture/LectureController.java index 0922a5e2f19edf7f6ce206fb6c4fddf8f50276d5..80b4f8e154f831ff52fc87745e0596c9f57b8c66 100644 --- a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/lecture/LectureController.java +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/lecture/LectureController.java @@ -2,11 +2,15 @@ package org.fuseri.modulelanguageschool.lecture; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; import jakarta.validation.Valid; import org.fuseri.model.dto.lecture.LectureCreateDto; import org.fuseri.model.dto.lecture.LectureDto; import org.fuseri.model.dto.user.UserDto; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -36,8 +40,13 @@ public class LectureController { */ @ApiOperation(value = "Create a new lecture") @PostMapping - public LectureDto create(@Valid @RequestBody LectureCreateDto lecture) { - return lectureFacade.create(lecture); + @ApiResponses(value = { + @ApiResponse(code = 201, message = "The lecture has been successfully created"), + @ApiResponse(code = 400, message = "The request body is invalid") + }) + public ResponseEntity<LectureDto> create(@Valid @RequestBody LectureCreateDto lecture) { + LectureDto lectureDto = lectureFacade.create(lecture); + return ResponseEntity.status(HttpStatus.CREATED).body(lectureDto); } /** @@ -48,8 +57,13 @@ public class LectureController { */ @ApiOperation(value = "Retrieve a lecture by its ID") @GetMapping("find/{courseId}") - public LectureDto find(@PathVariable Long courseId) { - return lectureFacade.findById(courseId); + @ApiResponses(value = { + @ApiResponse(code = 200, message = "The lecture has been found"), + @ApiResponse(code = 404, message = "The lecture with the specified ID does not exist") + }) + public ResponseEntity<LectureDto> find(@PathVariable Long courseId) { + LectureDto lectureDto = lectureFacade.findById(courseId); + return ResponseEntity.ok(lectureDto); } /** @@ -60,8 +74,12 @@ public class LectureController { */ @ApiOperation(value = "Retrieve a list of lectures for the corresponding course") @GetMapping("/findByCourse") - public List<LectureDto> findByCourse(@Valid @RequestParam Long courseId) { - return lectureFacade.findAll(courseId); + @ApiResponses(value = { + @ApiResponse(code = 200, message = "The list of lectures has been found"), + @ApiResponse(code = 404, message = "The course with the specified ID does not exist") + }) + public ResponseEntity<List<LectureDto>> findByCourse(@Valid @RequestParam Long courseId) { + return ResponseEntity.ok(lectureFacade.findAll(courseId)); } /** @@ -72,8 +90,13 @@ public class LectureController { */ @ApiOperation(value = "Update an existing lecture") @PutMapping("/update/{id}") - public LectureDto update(@PathVariable Long id, @Valid @RequestBody LectureCreateDto lecture) { - return lectureFacade.update(id, lecture); + @ApiResponses(value = { + @ApiResponse(code = 200, message = "The lecture has been successfully updated"), + @ApiResponse(code = 400, message = "The request body is invalid"), + @ApiResponse(code = 404, message = "The lecture with the specified ID does not exist") + }) + public ResponseEntity<LectureDto> update(@PathVariable Long id, @Valid @RequestBody LectureCreateDto lecture) { + return ResponseEntity.ok(lectureFacade.update(id, lecture)); } /** @@ -83,8 +106,13 @@ public class LectureController { */ @ApiOperation(value = "Delete a lecture by its ID") @DeleteMapping("/delete/{id}") - public void delete(@PathVariable Long id) { + @ApiResponses(value = { + @ApiResponse(code = 204, message = "The lecture has been successfully deleted"), + @ApiResponse(code = 404, message = "The lecture with the specified ID does not exist") + }) + public ResponseEntity<Void> delete(@PathVariable Long id) { lectureFacade.delete(id); + return ResponseEntity.noContent().build(); } @@ -97,8 +125,13 @@ public class LectureController { */ @ApiOperation(value = "Add lecturer to the existing lecture") @PatchMapping("/setLecturer/{id}") - public LectureDto setLecturer(@PathVariable Long id, @RequestBody UserDto lecturerDto) { - return lectureFacade.setLecturer(id, lecturerDto); + @ApiResponses(value = { + @ApiResponse(code = 200, message = "The lecture has been successfully updated"), + @ApiResponse(code = 400, message = "The request body is invalid"), + @ApiResponse(code = 404, message = "The lecture with the specified ID does not exist") + }) + public ResponseEntity<LectureDto> setLecturer(@PathVariable Long id, @RequestBody UserDto lecturerDto) { + return ResponseEntity.ok(lectureFacade.setLecturer(id, lecturerDto)); } /** @@ -110,8 +143,13 @@ public class LectureController { */ @ApiOperation(value = "Add student to the existing lecture") @PatchMapping("/enrol/{id}") - public LectureDto enrol(@PathVariable Long id, @RequestBody UserDto student) { - return lectureFacade.enrol(id, student); + @ApiResponses(value = { + @ApiResponse(code = 200, message = "The lecture has been successfully updated"), + @ApiResponse(code = 400, message = "The request body is invalid"), + @ApiResponse(code = 404, message = "The lecture with the specified ID does not exist") + }) + public ResponseEntity<LectureDto> enrol(@PathVariable Long id, @RequestBody UserDto student) { + return ResponseEntity.ok(lectureFacade.enrol(id, student)); } /** @@ -123,7 +161,12 @@ public class LectureController { */ @ApiOperation(value = "Remove student from the existing lecture") @PatchMapping("/expel/{id}") - public LectureDto expel(@PathVariable Long id, @RequestBody UserDto student) { - return lectureFacade.expel(id, student); + @ApiResponses(value = { + @ApiResponse(code = 200, message = "The lecture has been successfully updated"), + @ApiResponse(code = 400, message = "The request body is invalid"), + @ApiResponse(code = 404, message = "The lecture with the specified ID does not exist") + }) + public ResponseEntity<LectureDto> expel(@PathVariable Long id, @RequestBody UserDto student) { + return ResponseEntity.ok(lectureFacade.expel(id, student)); } } \ No newline at end of file diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/lecture/LectureFacade.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/lecture/LectureFacade.java index 08fe710ce9f4fc519a3dd1996d2ea1d99ed33066..ce9214dd71a6f10b6a9aa47187692e3ff6470fd7 100644 --- a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/lecture/LectureFacade.java +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/lecture/LectureFacade.java @@ -5,6 +5,7 @@ import org.fuseri.model.dto.course.ProficiencyLevelDto; import org.fuseri.model.dto.lecture.LectureCreateDto; import org.fuseri.model.dto.lecture.LectureDto; import org.fuseri.model.dto.user.UserDto; +import org.fuseri.modulelanguageschool.course.CourseService; import org.fuseri.modulelanguageschool.course.Language; import org.fuseri.modulelanguageschool.course.ProficiencyLevel; import org.fuseri.modulelanguageschool.user.UserMapper; @@ -22,17 +23,19 @@ public class LectureFacade { private final LectureService lectureService; private final LectureMapper lectureMapper; private final UserMapper userMapper; + private final CourseService courseService; @Autowired - public LectureFacade(LectureService lectureService, LectureMapper lectureMapper, UserMapper userMapper) { + public LectureFacade(LectureService lectureService, LectureMapper lectureMapper, UserMapper userMapper, CourseService courseService) { this.lectureService = lectureService; this.lectureMapper = lectureMapper; this.userMapper = userMapper; + this.courseService = courseService; } @Transactional public LectureDto create(LectureCreateDto dto) { - return lectureMapper.mapToDto(lectureService.save(lectureMapper.mapToLecture(dto))); + return lectureMapper.mapToDto(lectureService.save(lectureMapper.mapToLecture(dto, courseService))); } @Cacheable(cacheNames = "courses", key = "#id") @@ -48,7 +51,7 @@ public class LectureFacade { @Transactional public LectureDto update(Long id, LectureCreateDto dto) { - return lectureMapper.mapToDto(lectureService.update(id, lectureMapper.mapToLecture(dto))); + return lectureMapper.mapToDto(lectureService.update(id, lectureMapper.mapToLecture(dto, courseService))); } @Transactional diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/lecture/LectureMapper.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/lecture/LectureMapper.java index 8136a3e21de60635099c9284cfc71d2dec40ee2b..1eba68d367b58e75f46bf841871aae883cc25a0d 100644 --- a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/lecture/LectureMapper.java +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/lecture/LectureMapper.java @@ -2,24 +2,70 @@ package org.fuseri.modulelanguageschool.lecture; import org.fuseri.model.dto.lecture.LectureCreateDto; import org.fuseri.model.dto.lecture.LectureDto; +import org.fuseri.modulelanguageschool.course.CourseService; +import org.fuseri.modulelanguageschool.user.User; +import org.fuseri.modulelanguageschool.user.UserService; import org.mapstruct.Mapper; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; -@Mapper(componentModel = "spring") +@Mapper(componentModel = "spring", uses = {UserService.class}) public interface LectureMapper { - LectureDto mapToDto(Lecture lecture); - Lecture mapToLecture(LectureDto lectureDto); + default LectureDto mapToDto(Lecture lecture) { + if (lecture == null) { + return null; + } - List<LectureDto> mapToList(List<Lecture> lectures); + var dto = new LectureDto(lecture.getLectureFrom(), + lecture.getLectureTo(), + lecture.getTopic(), + lecture.getCapacity(), + lecture.getLecturer() == null ? null : lecture.getLecturer().getId(), + lecture.getCourse().getId(), + new ArrayList<>(lecture.getStudents().stream().map(User::getId).collect(Collectors.toList()))); + dto.setId(lecture.getId()); + return dto; + } + default Lecture mapToLecture(LectureDto lectureDto, CourseService courseService, UserService userService) { + if (lectureDto == null) { + return null; + } + var lecture = new Lecture(lectureDto.getLectureFrom(), + lectureDto.getLectureTo(), + lectureDto.getTopic(), + lectureDto.getCapacity(), + courseService.findById(lectureDto.getCourseId()), + userService.find(lectureDto.getLecturerId()), + new ArrayList<>()); + lecture.setId(lectureDto.getId()); + for (Long userId : lectureDto.getStudents()) { + lecture.enrolStudent(userService.find(userId)); + } + return lecture; + } - default Page<LectureDto> mapToPageDto(Page<Lecture> lectures) { - return new PageImpl<>(mapToList(lectures.getContent()), lectures.getPageable(), lectures.getTotalPages()); + default List<LectureDto> mapToList(List<Lecture> lectures) { + if (lectures == null) { + return null; + } + return new ArrayList<>(lectures.stream().map(this::mapToDto).toList()); } - Lecture mapToLecture(LectureCreateDto dto); + + default Lecture mapToLecture(LectureCreateDto lectureDto, CourseService courseService) { + if (lectureDto == null) { + return null; + } + return new Lecture(lectureDto.getLectureFrom(), + lectureDto.getLectureTo(), + lectureDto.getTopic(), + lectureDto.getCapacity(), + courseService.findById(lectureDto.getCourseId()), + null, + new ArrayList<>()); + } } diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/lecture/LectureService.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/lecture/LectureService.java index a9e90bcbae837c0785c4119e76f6d548163c19e7..a3d1ea7f96aaa79883689189331e88977aede3eb 100644 --- a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/lecture/LectureService.java +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/lecture/LectureService.java @@ -1,12 +1,13 @@ package org.fuseri.modulelanguageschool.lecture; -import org.fuseri.modulelanguageschool.common.ResourceNotFoundException; import org.fuseri.modulelanguageschool.course.Language; import org.fuseri.modulelanguageschool.course.ProficiencyLevel; import org.fuseri.modulelanguageschool.user.User; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.server.ResponseStatusException; import java.util.List; import java.util.Optional; @@ -29,7 +30,8 @@ public class LectureService { @Transactional(readOnly = true) public Lecture findById(Long id) { return lectureRepository.findById(id) - .orElseThrow(() -> new ResourceNotFoundException("Lecture with id: " + id + " was not found.")); + .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, + "Lecture with id: " + id + " was not found.")); } @Transactional(readOnly = true) @@ -42,15 +44,16 @@ public class LectureService { Optional<Lecture> optionalLecture = lectureRepository.findById(id); if (optionalLecture.isPresent()) { Lecture lecture = optionalLecture.get(); - lecture.setFrom(newLecture.getFrom()); - lecture.setTo(newLecture.getTo()); + lecture.setLectureFrom(newLecture.getLectureFrom()); + lecture.setLectureTo(newLecture.getLectureTo()); lecture.setTopic(newLecture.getTopic()); lecture.setCourse(newLecture.getCourse()); lecture.setLecturer(newLecture.getLecturer()); lecture.setStudents(newLecture.getStudents()); return lectureRepository.save(lecture); } else { - throw new ResourceNotFoundException("Lecture with id: " + id + " was not found."); + throw new ResponseStatusException(HttpStatus.NOT_FOUND, + "Lecture with id: " + id + " was not found."); } } @@ -59,14 +62,17 @@ public class LectureService { lectureRepository.deleteById(id); } + @Transactional public List<Lecture> findAll(Language language) { return lectureRepository.findAllByLang(language); } + @Transactional public List<Lecture> findAll(Language language, ProficiencyLevel proficiencyLevel) { return lectureRepository.findAllByLangProf(language, proficiencyLevel); } + @Transactional public Lecture enrol(Long id, User student) { Optional<Lecture> optionalLecture = lectureRepository.findById(id); if (optionalLecture.isPresent()) { @@ -74,10 +80,12 @@ public class LectureService { lecture.enrolStudent(student); return lectureRepository.save(lecture); } else { - throw new ResourceNotFoundException("Lecture with id: " + id + " was not found."); + throw new ResponseStatusException(HttpStatus.NOT_FOUND, + "Lecture with id: " + id + " was not found."); } } + @Transactional public Lecture expel(Long id, User student) { Optional<Lecture> optionalLecture = lectureRepository.findById(id); if (optionalLecture.isPresent()) { @@ -85,10 +93,12 @@ public class LectureService { lecture.expelStudent(student); return lectureRepository.save(lecture); } else { - throw new ResourceNotFoundException("Lecture with id: " + id + " was not found."); + throw new ResponseStatusException(HttpStatus.NOT_FOUND, + "Lecture with id: " + id + " was not found."); } } + @Transactional public Lecture setLecturer(Long id, User lecturer) { Optional<Lecture> optionalLecture = lectureRepository.findById(id); if (optionalLecture.isPresent()) { @@ -96,7 +106,8 @@ public class LectureService { lecture.setLecturer(lecturer); return lectureRepository.save(lecture); } else { - throw new ResourceNotFoundException("Lecture with id: " + id + " was not found."); + throw new ResponseStatusException(HttpStatus.NOT_FOUND, + "Lecture with id: " + id + " was not found."); } } } diff --git a/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/course/CourseTest.java b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/course/CourseControllerTest.java similarity index 69% rename from application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/course/CourseTest.java rename to application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/course/CourseControllerTest.java index ec5cff89f979d0424fc118be02aea6f3c420c7c1..21ed4e68ecce1e1025dc0f14f1525345589a0e36 100644 --- a/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/course/CourseTest.java +++ b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/course/CourseControllerTest.java @@ -15,32 +15,34 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMock import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import java.util.ArrayList; import java.util.List; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @SpringBootTest @AutoConfigureMockMvc -public class CourseTest { +public class CourseControllerTest { private final CourseCreateDto courseCreateDto = new CourseCreateDto("english b2 course", 10, LanguageTypeDto.ENGLISH, ProficiencyLevelDto.B2); - private final CourseDto courseDto = new CourseDto(0L, "english b2 course", 10, LanguageTypeDto.ENGLISH, ProficiencyLevelDto.B2); + private final CourseDto courseDto = new CourseDto("english b2 course", 10, LanguageTypeDto.ENGLISH, ProficiencyLevelDto.B2); + @Autowired ObjectMapper objectMapper; + @Autowired private MockMvc mockMvc; @MockBean - private CourseController courseController; + private CourseFacade courseFacade; public static String asJsonString(final Object obj) { try { @@ -52,24 +54,21 @@ public class CourseTest { @Test void createCourse() throws Exception { - Mockito.when(courseController.create(ArgumentMatchers.isA(CourseCreateDto.class))).thenReturn(courseDto); + Mockito.when(courseFacade.create(ArgumentMatchers.isA(CourseCreateDto.class))).thenReturn(courseDto); mockMvc.perform(post("/courses") .content(asJsonString(courseCreateDto)) .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) + .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.name").value("english b2 course")) .andExpect(jsonPath("$.capacity").value(10)) .andExpect(jsonPath("$.language").value("ENGLISH")) - .andExpect(jsonPath("$.proficiency").value("B2")) - .andExpect(jsonPath("$.id").exists()) - .andReturn().getResponse().getContentAsString(); + .andExpect(jsonPath("$.proficiency").value("B2")); } @Test void createInvalidCourse() throws Exception { CourseCreateDto invalidCourseCreateDto = new CourseCreateDto(null, null, null, null); - Mockito.when(courseController.create(ArgumentMatchers.isA(CourseCreateDto.class))).thenReturn(courseDto); mockMvc.perform(post("/courses") .content(asJsonString(invalidCourseCreateDto)) .contentType(MediaType.APPLICATION_JSON)) @@ -78,18 +77,17 @@ public class CourseTest { @Test void createCourseWithoutParameter() throws Exception { - Mockito.when(courseController.create(ArgumentMatchers.isA(CourseCreateDto.class))).thenReturn(courseDto); mockMvc.perform(post("/courses")) .andExpect(status().is4xxClientError()); } + @Test void findCourse() throws Exception { Long id = 0L; - Mockito.when(courseController.find(id)).thenReturn(courseDto); + Mockito.when(courseFacade.findById(id)).thenReturn(courseDto); mockMvc.perform(get("/courses/find/" + id)) .andExpect(status().isOk()) - .andExpect(jsonPath("$.id").value(id)) .andExpect(jsonPath("$.name").value("english b2 course")) .andExpect(jsonPath("$.capacity").value(10)) .andExpect(jsonPath("$.language").value("ENGLISH")) @@ -99,42 +97,37 @@ public class CourseTest { @Test void findCourseWithoutId() throws Exception { - Mockito.when(courseController.find(ArgumentMatchers.anyLong())).thenReturn(courseDto); mockMvc.perform(get("/courses/find/")) .andExpect(status().is4xxClientError()); } @Test void findAll() throws Exception { - int page = 0; - Mockito.when(courseController.findAll(page)).thenReturn(new PageImpl<>(new ArrayList<>())); - String response = mockMvc.perform(get("/courses/findAll").param("page", Integer.toString(page))) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - + Mockito.when(courseFacade.findAll((PageRequest) any())) + .thenReturn(new PageImpl<>(new ArrayList<>())); + String response = mockMvc.perform(get("/courses/findAll?page=0")) + .andExpect(status().is2xxSuccessful()).andReturn().getResponse().getContentAsString(); assertTrue(response.contains("\"content\":[]")); } @Test void findAllWithoutPage() throws Exception { -// Mockito.when(courseController.findAll(ArgumentMatchers.anyInt())).thenReturn(new PageImpl<>(new ArrayList<>())); mockMvc.perform(get("/courses/findAll")) .andExpect(status().is4xxClientError()); } + @Test void findAllByLang() throws Exception { int page = 0; LanguageTypeDto lang = LanguageTypeDto.ENGLISH; - Mockito.when(courseController.findAll(lang)).thenReturn(new ArrayList<>()); + Mockito.when(courseFacade.findAll(lang)).thenReturn(new ArrayList<>()); String response = mockMvc.perform(get("/courses/findAllByLang") .param("page", Integer.toString(page)) .param("lang", lang.toString())) .andExpect(status().isOk()) .andReturn().getResponse().getContentAsString(); - - assertThat("response", response, is("[]")); - } + assertTrue(response.endsWith("[]")); } @Test void findAllByLangWithoutLang() throws Exception { @@ -146,32 +139,23 @@ public class CourseTest { void findAllByLangProf() throws Exception { LanguageTypeDto lang = LanguageTypeDto.ENGLISH; ProficiencyLevelDto proficiencyLevel = ProficiencyLevelDto.A1; - Mockito.when(courseController.findAll(lang, proficiencyLevel)).thenReturn(new ArrayList<>()); + Mockito.when(courseFacade.findAll(lang, proficiencyLevel)).thenReturn(new ArrayList<>()); String response = mockMvc.perform(get("/courses/findAllByLangProf") .param("lang", lang.toString()) .param("prof", proficiencyLevel.toString())) .andExpect(status().isOk()) .andReturn().getResponse().getContentAsString(); - - assertThat("response", response, is("[]")); + assertTrue(response.endsWith("[]")); } @Test void findAllByLangProfWithoutParameters() throws Exception { - Mockito.when(courseController.findAll( - ArgumentMatchers.isA(LanguageTypeDto.class), - ArgumentMatchers.isA(ProficiencyLevelDto.class))) - .thenReturn(new ArrayList<>()); mockMvc.perform(get("/courses/findAllByLangProf")) .andExpect(status().is4xxClientError()); } @Test void findAllByLangProfWithoutLangProf() throws Exception { - Mockito.when(courseController.findAll( - ArgumentMatchers.isA(LanguageTypeDto.class), - ArgumentMatchers.isA(ProficiencyLevelDto.class))) - .thenReturn(new ArrayList<>()); String page = "0"; mockMvc.perform(get("/courses/findAllByLangProf").param("page", page)) .andExpect(status().is4xxClientError()); @@ -180,7 +164,7 @@ public class CourseTest { @Test void updateCourse() throws Exception { Long id = 0L; - Mockito.when(courseController.update(ArgumentMatchers.eq(id), + Mockito.when(courseFacade.update(ArgumentMatchers.eq(id), ArgumentMatchers.isA(CourseCreateDto.class))) .thenReturn(courseDto); @@ -192,15 +176,11 @@ public class CourseTest { .andExpect(jsonPath("$.capacity").value(10)) .andExpect(jsonPath("$.language").value("ENGLISH")) .andExpect(jsonPath("$.proficiency").value("B2")) - .andExpect(jsonPath("$.id").value(courseDto.getId())) - .andReturn().getResponse().getContentAsString(); + .andExpect(jsonPath("$.id").value(courseDto.getId())); } @Test void updateCourseWithoutParameter() throws Exception { - Mockito.when(courseController.update(ArgumentMatchers.anyLong(), - ArgumentMatchers.isA(CourseCreateDto.class))) - .thenReturn(courseDto); mockMvc.perform(put("/courses/update")) .andExpect(status().is4xxClientError()); } @@ -208,16 +188,14 @@ public class CourseTest { @Test void deleteCourse() throws Exception { Long id = 0L; - Mockito.doNothing().when(courseController).delete(id); + Mockito.doNothing().when(courseFacade).delete(id); mockMvc.perform(delete("/courses/delete/" + id)) - .andExpect(status().isOk()); + .andExpect(status().is2xxSuccessful()); } @Test void deleteCourseWithoutParameter() throws Exception { - Mockito.doNothing().when(courseController).delete(ArgumentMatchers.anyLong()); - mockMvc.perform(delete("/courses/delete/")) .andExpect(status().is4xxClientError()); } @@ -228,10 +206,10 @@ public class CourseTest { UserDto student = new UserDto("novakovat", "novakova@gamil.com", "Tereza", "Nováková", new AddressDto()); - CourseDto courseDtoWithStudent = new CourseDto(id, "english b2 course", 10, LanguageTypeDto.ENGLISH, ProficiencyLevelDto.B2); + CourseDto courseDtoWithStudent = new CourseDto("english b2 course", 10, LanguageTypeDto.ENGLISH, ProficiencyLevelDto.B2); courseDtoWithStudent.setStudentIds(new ArrayList<>(List.of(student.getId()))); - Mockito.when(courseController.enrol(ArgumentMatchers.eq(id), + Mockito.when(courseFacade.enrol(ArgumentMatchers.eq(id), ArgumentMatchers.isA(UserDto.class))).thenReturn(courseDtoWithStudent); mockMvc.perform(patch("/courses/enrol/" + id) @@ -242,25 +220,17 @@ public class CourseTest { .andExpect(jsonPath("$.capacity").value(10)) .andExpect(jsonPath("$.language").value("ENGLISH")) .andExpect(jsonPath("$.proficiency").value("B2")) - .andExpect(jsonPath("$.studentIds").exists()) - .andReturn().getResponse().getContentAsString(); + .andExpect(jsonPath("$.studentIds").exists()); } @Test void enrolCourseWithoutUserParameter() throws Exception { - String id = "0"; - Mockito.when(courseController.enrol(ArgumentMatchers.anyLong(), - ArgumentMatchers.isA(UserDto.class))) - .thenReturn(courseDto); - mockMvc.perform(patch("/courses/enrol/" + id)) + mockMvc.perform(patch("/courses/enrol/" + 0L)) .andExpect(status().is4xxClientError()); } @Test void enrolCourseWithoutCourseIdParameter() throws Exception { - Mockito.when(courseController.enrol(ArgumentMatchers.anyLong(), - ArgumentMatchers.isA(UserDto.class))) - .thenReturn(courseDto); UserDto student = new UserDto("novakovat", "novakova@gamil.com", "Tereza", "Nováková", new AddressDto()); @@ -273,7 +243,7 @@ public class CourseTest { @Test void expelCourse() throws Exception { Long id = 0L; - Mockito.when(courseController.expel(ArgumentMatchers.eq(id), + Mockito.when(courseFacade.expel(ArgumentMatchers.eq(id), ArgumentMatchers.isA(UserDto.class))) .thenReturn(courseDto); @@ -288,26 +258,17 @@ public class CourseTest { .andExpect(jsonPath("$.capacity").value(10)) .andExpect(jsonPath("$.language").value("ENGLISH")) .andExpect(jsonPath("$.proficiency").value("B2")) - .andExpect(jsonPath("$.studentIds").isEmpty()) - .andReturn().getResponse().getContentAsString(); + .andExpect(jsonPath("$.studentIds").isEmpty()); } @Test void expelCourseWithoutUserParameter() throws Exception { - Long id = 0L; - Mockito.when(courseController.expel(ArgumentMatchers.eq(id), - ArgumentMatchers.isA(UserDto.class))) - .thenReturn(courseDto); - - mockMvc.perform(patch("/courses/expel/" + id)) + mockMvc.perform(patch("/courses/expel/" + 0L)) .andExpect(status().is4xxClientError()); } @Test void deleteCourseWithoutCourseIdParameter() throws Exception { - Mockito.when(courseController.expel(ArgumentMatchers.anyLong(), - ArgumentMatchers.isA(UserDto.class))) - .thenReturn(courseDto); UserDto student = new UserDto("novakovat", "novakova@gamil.com", "Tereza", "Nováková", new AddressDto()); diff --git a/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/course/CourseFacadeTest.java b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/course/CourseFacadeTest.java new file mode 100644 index 0000000000000000000000000000000000000000..37c957dfcdd2630fa7e625b68152e6ec3c04cc78 --- /dev/null +++ b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/course/CourseFacadeTest.java @@ -0,0 +1,168 @@ +package org.fuseri.modulelanguageschool.course; + + +import org.fuseri.model.dto.course.CourseCreateDto; +import org.fuseri.model.dto.course.CourseDto; +import org.fuseri.model.dto.course.LanguageTypeDto; +import org.fuseri.model.dto.course.ProficiencyLevelDto; +import org.fuseri.model.dto.user.AddressDto; +import org.fuseri.model.dto.user.UserDto; +import org.fuseri.modulelanguageschool.user.User; +import org.fuseri.modulelanguageschool.user.UserMapper; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.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 static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + + +@SpringBootTest +@AutoConfigureMockMvc +final class CourseFacadeTest { + + private final UserDto USER = new UserDto("novakovat", + "novakova@gamil.com", "Tereza", "Nováková", new AddressDto()); + private final CourseDto courseDto = new CourseDto("AJ1", 10, + LanguageTypeDto.ENGLISH, ProficiencyLevelDto.A1); + private final CourseCreateDto courseCreateDto = new CourseCreateDto("AJ1", 10, + LanguageTypeDto.ENGLISH, ProficiencyLevelDto.A1); + private final Course course = new Course(); + private final User user = new User(); + private final List<Course> courseList = List.of(course); + private final List<CourseDto> courseDtoList = List.of(courseDto); + private final LanguageTypeDto languageTypeDto = LanguageTypeDto.ENGLISH; + private final ProficiencyLevelDto proficiencyLevelDto = ProficiencyLevelDto.B1; + + + @Autowired + private CourseFacade courseFacade; + + @MockBean + private CourseService courseService; + + @MockBean + private CourseMapper courseMapper; + + @MockBean + private UserMapper userMapper; + + @Test + void create() { + when(courseMapper.mapToCourse(courseCreateDto)).thenReturn(course); + when(courseService.save(course)).thenReturn(course); + when(courseMapper.mapToDto(course)).thenReturn(courseDto); + + CourseDto actualDto = courseFacade.create(courseCreateDto); + + assertEquals(courseDto, actualDto); + } + + @Test + void testFindById() { + Long id = 0L; + when(courseService.findById(id)).thenReturn(course); + when(courseMapper.mapToDto(course)).thenReturn(courseDto); + + CourseDto actualDto = courseFacade.findById(id); + + assertNotNull(actualDto); + assertEquals(courseDto, actualDto); + } + + @Test + void testFindAll() { + Pageable pageable = PageRequest.of(0, 10); + Page<Course> certificatePage = new PageImpl<>(List.of(course), pageable, 0); + Page<CourseDto> expectedPageDto = new PageImpl<>(List.of(courseDto), pageable, 0); + + when(courseService.findAll(pageable)).thenReturn(certificatePage); + when(courseMapper.mapToPageDto(certificatePage)).thenReturn(expectedPageDto); + + Page<CourseDto> actualPageDto = courseFacade.findAll(pageable); + + assertEquals(expectedPageDto, actualPageDto); + } + + @Test + void update() { + Long id = 1L; + when(courseMapper.mapToCourse(courseCreateDto)).thenReturn(course); + when(courseService.update(id, course)).thenReturn(course); + when(courseMapper.mapToDto(course)).thenReturn(courseDto); + + CourseDto actualDto = courseFacade.update(id, courseCreateDto); + + assertEquals(courseDto, actualDto); + } + + @Test + void testDelete() { + Long id = 1L; + courseFacade.delete(id); + verify(courseService).delete(id); + } + + @Test + void testFindAllByLanguage() { + when(courseService.findAll(any(Language.class))).thenReturn(courseList); + when(courseMapper.mapToList(courseList)).thenReturn(courseDtoList); + + List<CourseDto> actualDtoList = courseFacade.findAll(languageTypeDto); + + assertNotNull(actualDtoList); + assertEquals(courseDtoList, actualDtoList); + } + + @Test + void testFindAllByLanguageAndProf() { + when(courseService.findAll(any(Language.class), any(ProficiencyLevel.class))).thenReturn(courseList); + when(courseMapper.mapToList(courseList)).thenReturn(courseDtoList); + + List<CourseDto> actualDtoList = courseFacade.findAll(languageTypeDto, proficiencyLevelDto); + + assertNotNull(actualDtoList); + assertEquals(courseDtoList, actualDtoList); + } + + @Test + void testEnrol() { + Long id = 0L; + when(courseMapper.mapToDto(course)).thenReturn(courseDto); + when(userMapper.fromDto(USER)).thenReturn(user); + when(courseService.enrol(anyLong(), any(User.class))).thenReturn(course); + + CourseDto actualDto = courseFacade.enrol(id, USER); + + assertNotNull(actualDto); + assertEquals(courseDto, actualDto); + } + + @Test + void testExpel() { + Long id = 0L; + when(courseMapper.mapToDto(course)).thenReturn(courseDto); + when(userMapper.fromDto(USER)).thenReturn(user); + when(courseService.expel(anyLong(), any(User.class))).thenReturn(course); + + CourseDto actualDto = courseFacade.expel(id, USER); + + assertNotNull(actualDto); + assertEquals(courseDto, actualDto); + } + + + +} diff --git a/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/course/CourseMapperTest.java b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/course/CourseMapperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6009290ffc0fbcd188377b8cb6fdada81bb02baf --- /dev/null +++ b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/course/CourseMapperTest.java @@ -0,0 +1,126 @@ +package org.fuseri.modulelanguageschool.course; + +import org.fuseri.model.dto.course.CourseCreateDto; +import org.fuseri.model.dto.course.CourseDto; +import org.fuseri.model.dto.course.LanguageTypeDto; +import org.fuseri.model.dto.course.ProficiencyLevelDto; +import org.junit.jupiter.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.context.SpringBootTest; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; + +import java.util.Collections; +import java.util.List; + +@SpringBootTest +final class CourseMapperTest { + + private final CourseDto courseDto = new CourseDto("AJ1", 10, + LanguageTypeDto.ENGLISH, ProficiencyLevelDto.A1); + private final CourseCreateDto courseCreateDto = new CourseCreateDto("AJ1", 10, + LanguageTypeDto.ENGLISH, ProficiencyLevelDto.A1); + private final Course course = new Course("AJ1", 10, + Language.ENGLISH, ProficiencyLevel.A1, null); + @Autowired + private CourseMapper CourseMapper; + + @BeforeEach + void setUp() + { + course.setId(1L); + courseDto.setId(1L); + } + + @Test + void mapNullToDto() { + var createdDto = CourseMapper.mapToDto(null); + + Assertions.assertNull(createdDto); + } + + @Test + void mapToDto() { + var createdDto = CourseMapper.mapToDto(course); + + Assertions.assertEquals(courseDto, createdDto); + } + + @Test + void mapNullToCourseCourseDto() { + var createdCourse = CourseMapper.mapToCourse((CourseDto) null); + + Assertions.assertNull(createdCourse); + } + + @Test + void mapToCourseCourseDto() { + var createdCourse = CourseMapper.mapToCourse(courseDto); + + Assertions.assertEquals(course, createdCourse); + } + + @Test + void mapNullToList() { + var courseDtos = CourseMapper.mapToList(null); + + Assertions.assertNull(courseDtos); + } + + @Test + void mapToEmptyList() { + var courseDtos = CourseMapper.mapToList(Collections.emptyList()); + + Assertions.assertEquals(courseDtos.size(), 0); + } + + @Test + void mapToList() { + var courseDtos = CourseMapper.mapToList(Collections.singletonList(course)); + + Assertions.assertEquals(1, courseDtos.size()); + + + Assertions.assertEquals(courseDto, courseDtos.get(0)); + } + + @Test + void mapToEmptyPageDto() { + Page<CourseDto> pageDto = CourseMapper.mapToPageDto(Page.empty()); + + Assertions.assertEquals(1, pageDto.getTotalPages()); + } + + @Test + void mapToPageDto() { + List<Course> courses = List.of(course); + Page<Course> page = new PageImpl<>(courses, PageRequest.of(0, 1), courses.size()); + Page<CourseDto> pageDto = CourseMapper.mapToPageDto(page); + + Assertions.assertEquals(page.getTotalPages(), pageDto.getTotalPages()); + Assertions.assertEquals(page.getNumber(), pageDto.getNumber()); + Assertions.assertEquals(page.getNumberOfElements(), pageDto.getNumberOfElements()); + Assertions.assertEquals(page.getSize(), pageDto.getSize()); + Assertions.assertEquals(page.getTotalElements(), pageDto.getTotalElements()); + + Assertions.assertEquals(courseDto, pageDto.getContent().get(0)); + } + + @Test + void mapNullToCourseCourseCreateDto() { + var createdCourse = CourseMapper.mapToCourse((CourseCreateDto) null); + + Assertions.assertNull(createdCourse); + } + + @Test + void mapToCourseCourseCreateDto() { + var createdCourse = CourseMapper.mapToCourse(courseCreateDto); + + Assertions.assertEquals(course, createdCourse); + } + +} diff --git a/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/course/CourseRepositoryTest.java b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/course/CourseRepositoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..95ddc06b344397bd4c8bee8e9c55505f11ff85da --- /dev/null +++ b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/course/CourseRepositoryTest.java @@ -0,0 +1,92 @@ +package org.fuseri.modulelanguageschool.course; + +import org.junit.jupiter.api.Assertions; +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.boot.test.autoconfigure.orm.jpa.TestEntityManager; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@DataJpaTest +class CourseRepositoryTest { + + @Autowired + private TestEntityManager entityManager; + + @Autowired + private CourseRepository courseRepository; + + private final Course course = new Course("AJ1", 10, + Language.ENGLISH, ProficiencyLevel.A1, new ArrayList<>()); + + @Test + void saveCourse() { + Course saved = courseRepository.save(course); + + Assertions.assertNotNull(saved); + Assertions.assertEquals(course, saved); + } + + @Test + void findById() { + entityManager.persist(course); + entityManager.flush(); + + Course found = courseRepository.findById(course.getId()).orElse(null); + + Assertions.assertNotNull(found); + Assertions.assertEquals(found, course); + } + + + @Test + void findAllByLang() { + entityManager.persist(course); + entityManager.flush(); + + List<Course> found = courseRepository.findAllByLang(course.getLanguage()); + + Assertions.assertEquals(1, found.size()); + Assertions.assertEquals(found.get(0), course); + } + + @Test + void findAllByLangProf() { + entityManager.persist(course); + entityManager.flush(); + + List<Course> found = courseRepository.findAllByLangProf(course.getLanguage(), course.getProficiency()); + + Assertions.assertEquals(1, found.size()); + Assertions.assertEquals(found.get(0), course); + } + @Test + public void testFindAllCourses() { + Course course1 = new Course(); + Course course2 = new Course(); + + courseRepository.save(course1); + courseRepository.save(course2); + + Page<Course> coursePage = courseRepository.findAll(PageRequest.of(0, 42)); + + Assertions.assertEquals(2, coursePage.getTotalElements()); + Assertions.assertEquals(coursePage.getContent(), Arrays.asList(course1, course2)); + } + + @Test + public void testDeleteCourse() { + Long courseId = entityManager.persist(new Course()).getId(); + entityManager.flush(); + + courseRepository.deleteById(courseId); + + Assertions.assertTrue(courseRepository.findById(courseId).isEmpty()); + } + +} diff --git a/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/course/CourseServiceTest.java b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/course/CourseServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f0ccbe5ba0be6b5204fbd910ef174dfb2decf548 --- /dev/null +++ b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/course/CourseServiceTest.java @@ -0,0 +1,175 @@ +package org.fuseri.modulelanguageschool.course; + +import org.fuseri.modulelanguageschool.user.Address; +import org.fuseri.modulelanguageschool.user.User; +import org.fuseri.modulelanguageschool.user.UserType; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +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 org.springframework.web.server.ResponseStatusException; + +import java.util.*; + +import static org.mockito.Mockito.*; + +@SpringBootTest +final class CourseServiceTest { + + @MockBean + private CourseRepository courseRepository; + + @Autowired + private CourseService courseService; + + private final Course course = new Course("AJ1", 10, + Language.ENGLISH, ProficiencyLevel.A1, new ArrayList<>()); //todo + + private final User user = new User("novakovat", UserType.STUDENT, + "novakova@gamil.com", "password", "Tereza", + "Nováková", new Address(), List.of(), List.of()); + private final Course courseWithEnrolledStudent = new Course("AJ1", 10, + Language.ENGLISH, ProficiencyLevel.A1, new ArrayList<>(List.of(user))); + private final List<Course> courses = List.of(course, course); + + @Test + void save() { + when(courseRepository.save(course)).thenReturn(course); + + Course result = courseService.save(course); + + Assertions.assertEquals(course, result); + verify(courseRepository).save(course); + } + + @Test + void notFoundById() { + when(courseRepository.findById(anyLong())).thenReturn(Optional.empty()); + + Assertions.assertThrows(ResponseStatusException.class, () -> courseService.findById(anyLong())); + } + + @Test + void findById() { + when(courseRepository.findById(anyLong())).thenReturn(Optional.of(course)); + + Course result = courseService.findById(anyLong()); + + Assertions.assertEquals(course, result); + verify(courseRepository).findById(anyLong()); + } + + @Test + void findAll() { + Pageable pageable = PageRequest.of(0, 10); + Page<Course> page = new PageImpl<>(Collections.emptyList(), pageable, 0); + + when(courseRepository.findAll(pageable)).thenReturn(page); + + Page<Course> result = courseService.findAll(pageable); + + Assertions.assertEquals(page, result); + verify(courseRepository).findAll(pageable); + } + + @Test + void update() { + Long id = 1L; + when(courseRepository.findById(anyLong())).thenReturn(Optional.of(course)); + when(courseRepository.save(course)).thenReturn(course); + + Course result = courseService.update(id, course); + + Assertions.assertEquals(course, result); + verify(courseRepository).findById(anyLong()); + verify(courseRepository).save(course); + } + + @Test + void updateIdDoesNotExist() { + Long id = 1L; + when(courseRepository.findById(anyLong())).thenReturn(Optional.empty()); + + Assertions.assertThrows(ResponseStatusException.class, () -> courseService.update(id, course)); + } + + @Test + void delete() { + Long id = 1L; + courseService.delete(id); + + verify(courseRepository).deleteById(id); + } + + @Test + void findAllByLanguage() { + Language language = Language.ENGLISH; + when(courseRepository.findAllByLang(any(Language.class))).thenReturn(courses); + + List<Course> result = courseService.findAll(language); + + Assertions.assertEquals(courses, result); + verify(courseRepository).findAllByLang(language); + } + + @Test + void findAllByLanguageAndProf() { + Language language = Language.ENGLISH; + ProficiencyLevel proficiencyLevel = ProficiencyLevel.B1; + + when(courseRepository.findAllByLangProf(any(Language.class), any(ProficiencyLevel.class))).thenReturn(courses); + + List<Course> result = courseService.findAll(language, proficiencyLevel); + + Assertions.assertEquals(courses, result); + verify(courseRepository).findAllByLangProf(language, proficiencyLevel); + } + + @Test + void enrol() { + Long id = 1L; + when(courseRepository.findById(anyLong())).thenReturn(Optional.of(course)); + when(courseRepository.save(any(Course.class))).thenReturn(courseWithEnrolledStudent); + + Course result = courseService.enrol(id, user); + + Assertions.assertEquals(courseWithEnrolledStudent, result); + verify(courseRepository).findById(id); + verify(courseRepository).save(any(Course.class)); + } + + @Test + void enrolIdDoesNotExist() { + Long id = 1L; + when(courseRepository.findById(anyLong())).thenReturn(Optional.empty()); + + Assertions.assertThrows(ResponseStatusException.class, () -> courseService.enrol(id, user)); + } + + @Test + void expel() { + Long id = 1L; + when(courseRepository.findById(anyLong())).thenReturn(Optional.of(courseWithEnrolledStudent)); + when(courseRepository.save(any(Course.class))).thenReturn(course); + + Course result = courseService.expel(id, user); + + Assertions.assertEquals(course, result); + verify(courseRepository).findById(id); + verify(courseRepository).save(any(Course.class)); + } + + @Test + void expelIdDoesNotExist() { + Long id = 1L; + when(courseRepository.findById(anyLong())).thenReturn(Optional.empty()); + + Assertions.assertThrows(ResponseStatusException.class, () -> courseService.expel(id, user)); + } + +} diff --git a/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/lecture/LectureTest.java b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/lecture/LectureControllerTest.java similarity index 64% rename from application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/lecture/LectureTest.java rename to application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/lecture/LectureControllerTest.java index a0d327ac0bd7511e93297ff5de1a6f77ab54971e..6e61cfc638299ff9624680830328ca31f6c184a4 100644 --- a/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/lecture/LectureTest.java +++ b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/lecture/LectureControllerTest.java @@ -15,57 +15,70 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; + import java.time.LocalDateTime; import java.util.ArrayList; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; +import java.util.Collections; + +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @SpringBootTest @AutoConfigureMockMvc -public class LectureTest { +public class LectureControllerTest { + + private final LocalDateTime now = LocalDateTime.now(); + private final LectureCreateDto lectureCreateDto = new LectureCreateDto( + now.plusDays(2), + now.plusDays(2).plusHours(2), + "Learning how to spell deprecated", + 10, 0L); + private final LectureDto lectureDto = new LectureDto( + now.plusDays(2), + now.plusDays(2).plusHours(2), + "Learning how to spell deprecated", + 10, 0L, 0L, Collections.emptyList()); + @Autowired ObjectMapper objectMapper; + @Autowired private MockMvc mockMvc; @MockBean - private LectureController lectureController; + private LectureFacade lectureFacade; - private final LectureCreateDto lectureCreateDto = new LectureCreateDto( - LocalDateTime.now().plusDays(2), - LocalDateTime.now().plusDays(2).plusHours(2), - "Learning how to spell deprecated", - 10, 0L); - private final LectureDto lectureDto = new LectureDto( - LocalDateTime.now().plusDays(2), - LocalDateTime.now().plusDays(2).plusHours(2), - "Learning how to spell deprecated", - 10, 0L, 0L); + public static String asJsonString(final Object obj) { + try { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new JavaTimeModule()); + return mapper.writeValueAsString(obj); + } catch (Exception e) { + throw new RuntimeException(e); + } + } @Test void createLecture() throws Exception { - Mockito.when(lectureController.create(ArgumentMatchers.isA(LectureCreateDto.class))).thenReturn(lectureDto); + Mockito.when(lectureFacade.create(ArgumentMatchers.isA(LectureCreateDto.class))).thenReturn(lectureDto); mockMvc.perform(post("/lectures") .content(asJsonString(lectureCreateDto)) .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.from").isNotEmpty()) - .andExpect(jsonPath("$.to").isNotEmpty()) + .andExpect(status().is2xxSuccessful()) + .andExpect(jsonPath("$.lectureFrom").isNotEmpty()) + .andExpect(jsonPath("$.lectureTo").isNotEmpty()) .andExpect(jsonPath("$.topic").value("Learning how to spell deprecated")) .andExpect(jsonPath("$.capacity").value("10")) .andExpect(jsonPath("$.lecturerId").value("0")) - .andExpect(jsonPath("$.courseId").value("0")) - .andReturn().getResponse().getContentAsString(); + .andExpect(jsonPath("$.courseId").value("0")); } @Test void createInvalidLecture() throws Exception { LectureCreateDto invalidLectureCreateDto = new LectureCreateDto(null, null, null, null, null); - Mockito.when(lectureController.create(ArgumentMatchers.isA(LectureCreateDto.class))).thenReturn(lectureDto); mockMvc.perform(post("/lectures") .content(asJsonString(invalidLectureCreateDto)) .contentType(MediaType.APPLICATION_JSON)) @@ -74,7 +87,6 @@ public class LectureTest { @Test void createLectureWithoutParameter() throws Exception { - Mockito.when(lectureController.create(ArgumentMatchers.isA(LectureCreateDto.class))).thenReturn(lectureDto); mockMvc.perform(post("/lectures")) .andExpect(status().is4xxClientError()); } @@ -82,21 +94,19 @@ public class LectureTest { @Test void findLecture() throws Exception { Long id = 0L; - Mockito.when(lectureController.find(id)).thenReturn(lectureDto); + Mockito.when(lectureFacade.findById(id)).thenReturn(lectureDto); mockMvc.perform(get("/lectures/find/" + id)) .andExpect(status().isOk()) - .andExpect(jsonPath("$.from").isNotEmpty()) - .andExpect(jsonPath("$.to").isNotEmpty()) + .andExpect(jsonPath("$.lectureFrom").isNotEmpty()) + .andExpect(jsonPath("$.lectureTo").isNotEmpty()) .andExpect(jsonPath("$.topic").value("Learning how to spell deprecated")) .andExpect(jsonPath("$.capacity").value("10")) .andExpect(jsonPath("$.lecturerId").value("0")) - .andExpect(jsonPath("$.courseId").value("0")) - .andReturn().getResponse().getContentAsString(); + .andExpect(jsonPath("$.courseId").value("0")); } @Test void findLectureWithoutId() throws Exception { - Mockito.when(lectureController.find(ArgumentMatchers.anyLong())).thenReturn(lectureDto); mockMvc.perform(get("/lectures/find/")) .andExpect(status().is4xxClientError()); } @@ -104,18 +114,16 @@ public class LectureTest { @Test void findLecturesByCourse() throws Exception { Long id = 0L; - Mockito.when(lectureController.findByCourse(id)).thenReturn(new ArrayList<>()); + Mockito.when(lectureFacade.findAll(id)).thenReturn(new ArrayList<>()); String response = mockMvc.perform(get("/lectures/findByCourse") .param("courseId", String.valueOf(id))) .andExpect(status().isOk()) .andReturn().getResponse().getContentAsString(); - - assertThat("response", response, is("[]")); + assertTrue(response.endsWith("[]")); } @Test void findLecturesByCourseWithoutParameter() throws Exception { - Mockito.when(lectureController.findByCourse(ArgumentMatchers.anyLong())).thenReturn(new ArrayList<>()); mockMvc.perform(get("/lectures/findByCourse")) .andExpect(status().is4xxClientError()); } @@ -123,27 +131,23 @@ public class LectureTest { @Test void updateLecture() throws Exception { Long id = 0L; - Mockito.when(lectureController.update(ArgumentMatchers.eq(id), - ArgumentMatchers.isA(LectureCreateDto.class))) + Mockito.when(lectureFacade.update(ArgumentMatchers.eq(id), + ArgumentMatchers.isA(LectureCreateDto.class))) .thenReturn(lectureDto); mockMvc.perform(put("/lectures/update/" + id) .content(asJsonString(lectureCreateDto)) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) - .andExpect(jsonPath("$.from").isNotEmpty()) - .andExpect(jsonPath("$.to").isNotEmpty()) + .andExpect(jsonPath("$.lectureFrom").isNotEmpty()) + .andExpect(jsonPath("$.lectureTo").isNotEmpty()) .andExpect(jsonPath("$.topic").value("Learning how to spell deprecated")) .andExpect(jsonPath("$.capacity").value("10")) .andExpect(jsonPath("$.lecturerId").value("0")) - .andExpect(jsonPath("$.courseId").value("0")) - .andReturn().getResponse().getContentAsString(); + .andExpect(jsonPath("$.courseId").value("0")); } @Test void updateLectureWithoutParameter() throws Exception { - Mockito.when(lectureController. - update(ArgumentMatchers.anyLong(), ArgumentMatchers.isA(LectureCreateDto.class))) - .thenReturn(lectureDto); mockMvc.perform(put("/lectures/update")) .andExpect(status().is4xxClientError()); } @@ -151,14 +155,13 @@ public class LectureTest { @Test void deleteLecture() throws Exception { Long id = 0L; - Mockito.doNothing().when(lectureController).delete(id); + Mockito.doNothing().when(lectureFacade).delete(id); mockMvc.perform(delete("/lectures/delete/" + id)) - .andExpect(status().isOk()); + .andExpect(status().is2xxSuccessful()); } @Test void deleteCourseWithoutParameter() throws Exception { - Mockito.doNothing().when(lectureController).delete(ArgumentMatchers.anyLong()); mockMvc.perform(delete("/lectures/delete/")) .andExpect(status().is4xxClientError()); } @@ -166,29 +169,25 @@ public class LectureTest { @Test void setLecturerForLecture() throws Exception { Long id = 0L; - Mockito.when(lectureController.setLecturer(ArgumentMatchers.eq(id), - ArgumentMatchers.isA(UserDto.class))) + Mockito.when(lectureFacade.setLecturer(ArgumentMatchers.eq(id), + ArgumentMatchers.isA(UserDto.class))) .thenReturn(lectureDto); - UserDto student = new UserDto("novakovat","novakova@gamil.com", "Tereza", + UserDto student = new UserDto("novakovat", "novakova@gamil.com", "Tereza", "Nováková", new AddressDto()); mockMvc.perform(patch("/lectures/setLecturer/" + id) .content(asJsonString(student)) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) - .andExpect(jsonPath("$.from").isNotEmpty()) - .andExpect(jsonPath("$.to").isNotEmpty()) + .andExpect(jsonPath("$.lectureFrom").isNotEmpty()) + .andExpect(jsonPath("$.lectureTo").isNotEmpty()) .andExpect(jsonPath("$.topic").value("Learning how to spell deprecated")) .andExpect(jsonPath("$.capacity").value("10")) .andExpect(jsonPath("$.lecturerId").value("0")) - .andExpect(jsonPath("$.courseId").value("0")) - .andReturn().getResponse().getContentAsString(); + .andExpect(jsonPath("$.courseId").value("0")); } @Test void setLecturerForLectureWithoutParameters() throws Exception { - Mockito.when(lectureController.setLecturer(ArgumentMatchers.anyLong(), - ArgumentMatchers.isA(UserDto.class))) - .thenReturn(lectureDto); mockMvc.perform(patch("/lectures/setLecturer")) .andExpect(status().is4xxClientError()); } @@ -196,29 +195,25 @@ public class LectureTest { @Test void enrolLecture() throws Exception { Long id = 0L; - Mockito.when(lectureController.enrol(ArgumentMatchers.eq(id), - ArgumentMatchers.isA(UserDto.class))) + Mockito.when(lectureFacade.enrol(ArgumentMatchers.eq(id), + ArgumentMatchers.isA(UserDto.class))) .thenReturn(lectureDto); - UserDto student = new UserDto("novakovat","novakova@gamil.com", "Tereza", + UserDto student = new UserDto("novakovat", "novakova@gamil.com", "Tereza", "Nováková", new AddressDto()); mockMvc.perform(patch("/lectures/enrol/" + id) .content(asJsonString(student)) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) - .andExpect(jsonPath("$.from").isNotEmpty()) - .andExpect(jsonPath("$.to").isNotEmpty()) + .andExpect(jsonPath("$.lectureFrom").isNotEmpty()) + .andExpect(jsonPath("$.lectureTo").isNotEmpty()) .andExpect(jsonPath("$.topic").value("Learning how to spell deprecated")) .andExpect(jsonPath("$.capacity").value("10")) .andExpect(jsonPath("$.lecturerId").value("0")) - .andExpect(jsonPath("$.courseId").value("0")) - .andReturn().getResponse().getContentAsString(); + .andExpect(jsonPath("$.courseId").value("0")); } @Test void enrolCourseWithoutUserParameters() throws Exception { - Mockito.when(lectureController.enrol(ArgumentMatchers.anyLong(), - ArgumentMatchers.isA(UserDto.class))) - .thenReturn(lectureDto); mockMvc.perform(patch("/lectures/enrol")) .andExpect(status().is4xxClientError()); } @@ -226,41 +221,27 @@ public class LectureTest { @Test void expelLecture() throws Exception { Long id = 0L; - Mockito.when(lectureController.expel(ArgumentMatchers.eq(id), - ArgumentMatchers.isA(UserDto.class))) + Mockito.when(lectureFacade.expel(ArgumentMatchers.eq(id), + ArgumentMatchers.isA(UserDto.class))) .thenReturn(lectureDto); - UserDto student = new UserDto("novakovat","novakova@gamil.com", "Tereza", + UserDto student = new UserDto("novakovat", "novakova@gamil.com", "Tereza", "Nováková", new AddressDto()); mockMvc.perform(patch("/lectures/expel/" + id) .content(asJsonString(student)) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) - .andExpect(jsonPath("$.from").isNotEmpty()) - .andExpect(jsonPath("$.to").isNotEmpty()) + .andExpect(jsonPath("$.lectureFrom").isNotEmpty()) + .andExpect(jsonPath("$.lectureTo").isNotEmpty()) .andExpect(jsonPath("$.topic").value("Learning how to spell deprecated")) .andExpect(jsonPath("$.capacity").value("10")) .andExpect(jsonPath("$.lecturerId").value("0")) - .andExpect(jsonPath("$.courseId").value("0")) - .andReturn().getResponse().getContentAsString(); + .andExpect(jsonPath("$.courseId").value("0")); } @Test void expelCourseWithoutUserParameters() throws Exception { - Mockito.when(lectureController.expel(ArgumentMatchers.anyLong(), - ArgumentMatchers.isA(UserDto.class))) - .thenReturn(lectureDto); mockMvc.perform(patch("/lectures/expel")) .andExpect(status().is4xxClientError()); } - public static String asJsonString(final Object obj) { - try { - ObjectMapper mapper = new ObjectMapper(); - mapper.registerModule(new JavaTimeModule()); - return mapper.writeValueAsString(obj); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } diff --git a/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/lecture/LectureFacadeTest.java b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/lecture/LectureFacadeTest.java new file mode 100644 index 0000000000000000000000000000000000000000..78f5924299f2ace9182566fb19f32cd9de49c2c2 --- /dev/null +++ b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/lecture/LectureFacadeTest.java @@ -0,0 +1,186 @@ +package org.fuseri.modulelanguageschool.lecture; + + +import org.fuseri.model.dto.course.LanguageTypeDto; +import org.fuseri.model.dto.course.ProficiencyLevelDto; +import org.fuseri.model.dto.lecture.LectureCreateDto; +import org.fuseri.model.dto.lecture.LectureDto; +import org.fuseri.model.dto.user.AddressDto; +import org.fuseri.model.dto.user.UserDto; +import org.fuseri.modulelanguageschool.course.CourseService; +import org.fuseri.modulelanguageschool.course.Language; +import org.fuseri.modulelanguageschool.course.ProficiencyLevel; +import org.fuseri.modulelanguageschool.user.User; +import org.fuseri.modulelanguageschool.user.UserMapper; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; + +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + + +@SpringBootTest +@AutoConfigureMockMvc +final class LectureFacadeTest { + + private final UserDto USER = new UserDto("novakovat", + "novakova@gamil.com", "Tereza", "Nováková", new AddressDto()); + private final LectureCreateDto lectureCreateDto = new LectureCreateDto( + LocalDateTime.now().plusDays(2), + LocalDateTime.now().plusDays(2).plusHours(2), + "Learning how to spell deprecated", + 10, 0L); + private final LectureDto lectureDto = new LectureDto( + LocalDateTime.now().plusDays(2), + LocalDateTime.now().plusDays(2).plusHours(2), + "Learning how to spell deprecated", + 10, 0L, 0L, Collections.emptyList()); + private final Lecture lecture = new Lecture(); + private final User user = new User(); + private final List<Lecture> lectureList = List.of(lecture); + private final List<LectureDto> lectureDtoList = List.of(lectureDto); + private final LanguageTypeDto languageTypeDto = LanguageTypeDto.ENGLISH; + private final ProficiencyLevelDto proficiencyLevelDto = ProficiencyLevelDto.B1; + + + @Autowired + private LectureFacade lectureFacade; + + @MockBean + private LectureService lectureService; + + @MockBean + private LectureMapper lectureMapper; + + @MockBean + private UserMapper userMapper; + + @Autowired + private CourseService courseService; + + @Test + void create() { + when(lectureMapper.mapToLecture(lectureCreateDto, courseService)).thenReturn(lecture); + when(lectureService.save(lecture)).thenReturn(lecture); + when(lectureMapper.mapToDto(lecture)).thenReturn(lectureDto); + + LectureDto actualDto = lectureFacade.create(lectureCreateDto); + + assertEquals(lectureDto, actualDto); + } + + @Test + void testFindById() { + Long id = 0L; + when(lectureService.findById(id)).thenReturn(lecture); + when(lectureMapper.mapToDto(lecture)).thenReturn(lectureDto); + + LectureDto actualDto = lectureFacade.findById(id); + + assertNotNull(actualDto); + assertEquals(lectureDto, actualDto); + } + + @Test + void testFindAll() { + var id = 1L; + when(lectureService.findAllByCourse(anyLong())).thenReturn(lectureList); + when(lectureMapper.mapToList(lectureList)).thenReturn(lectureDtoList); + + List<LectureDto> actualPageDtos = lectureFacade.findAll(id); + + assertEquals(lectureDtoList, actualPageDtos); + } + + @Test + void update() { + Long id = 1L; + when(lectureMapper.mapToLecture(lectureCreateDto, courseService)).thenReturn(lecture); + when(lectureService.update(id, lecture)).thenReturn(lecture); + when(lectureMapper.mapToDto(lecture)).thenReturn(lectureDto); + + LectureDto actualDto = lectureFacade.update(id, lectureCreateDto); + + assertEquals(lectureDto, actualDto); + } + + @Test + void testDelete() { + Long id = 1L; + lectureFacade.delete(id); + verify(lectureService).delete(id); + } + + @Test + void testFindAllByLanguage() { + when(lectureService.findAll(any(Language.class))).thenReturn(lectureList); + when(lectureMapper.mapToList(lectureList)).thenReturn(lectureDtoList); + + List<LectureDto> actualDtoList = lectureFacade.findAll(languageTypeDto); + + assertNotNull(actualDtoList); + assertEquals(lectureDtoList, actualDtoList); + } + + @Test + void testFindAllByLanguageAndProf() { + when(lectureService.findAll(any(Language.class), any(ProficiencyLevel.class))).thenReturn(lectureList); + when(lectureMapper.mapToList(lectureList)).thenReturn(lectureDtoList); + + List<LectureDto> actualDtoList = lectureFacade.findAll(languageTypeDto, proficiencyLevelDto); + + assertNotNull(actualDtoList); + assertEquals(lectureDtoList, actualDtoList); + } + + @Test + void testEnrol() { + Long id = 0L; + when(lectureMapper.mapToDto(lecture)).thenReturn(lectureDto); + when(userMapper.fromDto(USER)).thenReturn(user); + when(lectureService.enrol(anyLong(), any(User.class))).thenReturn(lecture); + + LectureDto actualDto = lectureFacade.enrol(id, USER); + + assertNotNull(actualDto); + assertEquals(lectureDto, actualDto); + } + + @Test + void testExpel() { + Long id = 0L; + when(lectureMapper.mapToDto(lecture)).thenReturn(lectureDto); + when(userMapper.fromDto(USER)).thenReturn(user); + when(lectureService.expel(anyLong(), any(User.class))).thenReturn(lecture); + + LectureDto actualDto = lectureFacade.expel(id, USER); + + assertNotNull(actualDto); + assertEquals(lectureDto, actualDto); + } + + @Test + void testSetLecturer() { + Long id = 0L; + when(lectureMapper.mapToDto(lecture)).thenReturn(lectureDto); + when(userMapper.fromDto(USER)).thenReturn(user); + when(lectureService.setLecturer(anyLong(), any(User.class))).thenReturn(lecture); + + LectureDto actualDto = lectureFacade.setLecturer(id, USER); + + assertNotNull(actualDto); + assertEquals(lectureDto, actualDto); + } +} + diff --git a/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/lecture/LectureMapperTest.java b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/lecture/LectureMapperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..28e5a1e57fcce0bb1eebf2a534760376cc130b86 --- /dev/null +++ b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/lecture/LectureMapperTest.java @@ -0,0 +1,148 @@ +package org.fuseri.modulelanguageschool.lecture; + +import org.fuseri.model.dto.lecture.LectureCreateDto; +import org.fuseri.model.dto.lecture.LectureDto; +import org.fuseri.modulelanguageschool.course.Course; +import org.fuseri.modulelanguageschool.course.CourseService; +import org.fuseri.modulelanguageschool.course.Language; +import org.fuseri.modulelanguageschool.course.ProficiencyLevel; +import org.fuseri.modulelanguageschool.user.Address; +import org.fuseri.modulelanguageschool.user.User; +import org.fuseri.modulelanguageschool.user.UserService; +import org.fuseri.modulelanguageschool.user.UserType; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.when; + +@SpringBootTest +final class LectureMapperTest { + + private final LocalDateTime now = LocalDateTime.now(); + + private final User lecturer = new User("dolezelt", UserType.LECTURER, + "dolezel@gmail.com", "password", "Tomáš", + "Doležel", new Address(), List.of(), List.of()); + private final User student = new User("novakovat", UserType.STUDENT, + "novakova@gmail.com", "password", "Tereza", + "Nováková", new Address(), List.of(), List.of()); + + private final Course course = new Course("AJ1", 10, + Language.ENGLISH, ProficiencyLevel.A1, null); + + private final LectureCreateDto lectureCreateDto = new LectureCreateDto( + now.plusDays(2), + now.plusDays(2).plusHours(2), + "Learning how to spell deprecated", + 10, course.getId()); + private final LectureDto lectureDto = new LectureDto( + now.plusDays(2), + now.plusDays(2).plusHours(2), + "Learning how to spell deprecated", + 10, lecturer.getId(), course.getId(), Collections.emptyList()); + private final Lecture newLecture = new Lecture( + now.plusDays(2), + now.plusDays(2).plusHours(2), + "Learning how to spell deprecated", + 10, + course, null, new ArrayList<>(List.of())); + + private final Lecture lecture = new Lecture( + now.plusDays(2), + now.plusDays(2).plusHours(2), + "Learning how to spell deprecated", + 10, + course, lecturer, new ArrayList<>(List.of())); + + @Autowired + private org.fuseri.modulelanguageschool.lecture.LectureMapper LectureMapper; + + @MockBean + private CourseService courseService; + + @MockBean + private UserService userService; + + @Test + void mapNullToDto() { + var createdDto = LectureMapper.mapToDto(null); + + Assertions.assertNull(createdDto); + } + + @Test + void mapToDto() { + var createdDto = LectureMapper.mapToDto(lecture); + + Assertions.assertEquals(lectureDto, createdDto); + } + + @Test + void mapNullToLectureDto() { + var createdLecture = LectureMapper.mapToLecture((LectureDto) null, courseService, userService); + + Assertions.assertNull(createdLecture); + } + + @Test + void mapToLectureDto() { + when(courseService.findById(any())).thenReturn(course); + when(userService.find(any())).thenReturn(student); + + var createdLecture = LectureMapper.mapToLecture(lectureDto, courseService, userService); + Assertions.assertEquals(lecture, createdLecture); + } + + @Test + void mapNullToList() { + var lectureDtos = LectureMapper.mapToList(null); + + Assertions.assertNull(lectureDtos); + } + + @Test + void mapToEmptyList() { + var lectureDtos = LectureMapper.mapToList(Collections.emptyList()); + + Assertions.assertEquals(lectureDtos.size(), 0); + } + + @Test + void mapToList() { + when(courseService.findById(anyLong())).thenReturn(course); + when(userService.find(anyLong())).thenReturn(lecturer); + + var lectureDtos = LectureMapper.mapToList(Collections.singletonList(lecture)); + + Assertions.assertEquals(1, lectureDtos.size()); + Assertions.assertEquals(lectureDto, lectureDtos.get(0)); + } + + @Test + void mapNullToLectureLectureCreateDto() { + var createdLecture = LectureMapper.mapToLecture((LectureCreateDto) null, courseService); + + Assertions.assertNull(createdLecture); + } + + @Test + void mapToLectureLectureCreateDto() { + when(courseService.findById(any())).thenReturn(course); + + var createdLecture = LectureMapper.mapToLecture(lectureCreateDto, courseService); + + Assertions.assertEquals(newLecture, createdLecture); + } + +} + diff --git a/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/lecture/LectureRepositoryTest.java b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/lecture/LectureRepositoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..242f478f6474cff9d8f33e98509910e449fb4779 --- /dev/null +++ b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/lecture/LectureRepositoryTest.java @@ -0,0 +1,135 @@ +package org.fuseri.modulelanguageschool.lecture; + +import org.fuseri.modulelanguageschool.course.Course; +import org.fuseri.modulelanguageschool.course.Language; +import org.fuseri.modulelanguageschool.course.ProficiencyLevel; +import org.fuseri.modulelanguageschool.user.Address; +import org.fuseri.modulelanguageschool.user.User; +import org.fuseri.modulelanguageschool.user.UserType; +import org.junit.jupiter.api.Assertions; +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.boot.test.autoconfigure.orm.jpa.TestEntityManager; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@DataJpaTest +class LectureRepositoryTest { + + @Autowired + private TestEntityManager entityManager; + + @Autowired + private LectureRepository lectureRepository; + + + private final Course course = new Course("AJ1", 10, + Language.ENGLISH, ProficiencyLevel.A1, null); + private final User student = new User("novakovat", UserType.STUDENT, + "novakova@gmail.com", "password", "Tereza", + "Nováková", new Address(), List.of(), List.of()); + private final User lecturer = new User("dolezelt", UserType.LECTURER, + "dolezel@gmail.com", "password", "Tomáš", + "Doležel", new Address(), List.of(), List.of()); + private final Lecture lecture = new Lecture( + LocalDateTime.now().plusDays(2), + LocalDateTime.now().plusDays(2).plusHours(2), + "Learning how to spell deprecated", + 10, + course, lecturer, new ArrayList<>(List.of(student))); + + @Test + void saveLecture() { + Lecture saved = lectureRepository.save(lecture); + + Assertions.assertNotNull(saved); + Assertions.assertEquals(lecture, saved); + } + + @Test + void findById() { + entityManager.persist(lecturer); + entityManager.persist(student); + entityManager.persist(course); + entityManager.persist(lecture); + entityManager.flush(); + + Lecture found = lectureRepository.findById(lecture.getId()).orElse(null); + + Assertions.assertNotNull(found); + Assertions.assertEquals(found, lecture); + } + + @Test + void findAllByCourse() { + entityManager.persist(lecturer); + entityManager.persist(student); + entityManager.persist(course); + entityManager.persist(lecture); + entityManager.flush(); + + List<Lecture> found = lectureRepository.findAllByCourse(lecture.getCourse().getId()); + + Assertions.assertEquals(1, found.size()); + Assertions.assertEquals(found.get(0), lecture); + } + + @Test + void findAllByLang() { + entityManager.persist(lecturer); + entityManager.persist(student); + entityManager.persist(course); + entityManager.persist(lecture); + entityManager.flush(); + + List<Lecture> found = lectureRepository.findAllByLang(lecture.getCourse().getLanguage()); + + Assertions.assertEquals(1, found.size()); + Assertions.assertEquals(found.get(0), lecture); + } + + @Test + void findAllByLangProf() { + entityManager.persist(lecturer); + entityManager.persist(student); + entityManager.persist(course); + entityManager.persist(lecture); + entityManager.flush(); + + List<Lecture> found = lectureRepository.findAllByLangProf(lecture.getCourse().getLanguage(), + lecture.getCourse().getProficiency()); + + Assertions.assertEquals(1, found.size()); + Assertions.assertEquals(found.get(0), lecture); + } + @Test + void testFindAllLectures() { + Lecture lecture1 = new Lecture(); + Lecture lecture2 = new Lecture(); + + lectureRepository.save(lecture1); + lectureRepository.save(lecture2); + + Page<Lecture> lecturePage = lectureRepository.findAll(PageRequest.of(0, 42)); + + Assertions.assertEquals(2, lecturePage.getTotalElements()); + Assertions.assertEquals(lecturePage.getContent(), Arrays.asList(lecture1, lecture2)); + } + + @Test + void testDeleteLecture() { + Long lectureId = entityManager.persist(new Lecture()).getId(); + entityManager.flush(); + + lectureRepository.deleteById(lectureId); + + Assertions.assertTrue(lectureRepository.findById(lectureId).isEmpty()); + } +} + diff --git a/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/lecture/LectureServiceTest.java b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/lecture/LectureServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..bbb681e5ccbef75466b32349f9c24fd6a648a52f --- /dev/null +++ b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/lecture/LectureServiceTest.java @@ -0,0 +1,179 @@ +package org.fuseri.modulelanguageschool.lecture; + +import org.fuseri.modulelanguageschool.course.Course; +import org.fuseri.modulelanguageschool.course.Language; +import org.fuseri.modulelanguageschool.course.ProficiencyLevel; +import org.fuseri.modulelanguageschool.user.Address; +import org.fuseri.modulelanguageschool.user.User; +import org.fuseri.modulelanguageschool.user.UserType; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.web.server.ResponseStatusException; + +import java.time.LocalDateTime; +import java.util.*; + +import static org.mockito.Mockito.*; + +@SpringBootTest +final class LectureServiceTest { + + @MockBean + private LectureRepository lectureRepository; + + @Autowired + private LectureService lectureService; + + private final Course course = new Course("AJ1", 10, + Language.ENGLISH, ProficiencyLevel.A1, null); + private final User student = new User("novakovat", UserType.STUDENT, + "novakova@gmail.com", "password", "Tereza", + "Nováková", new Address(), List.of(), List.of()); + private final User lecturer = new User("dolezelt", UserType.LECTURER, + "dolezel@gmail.com", "password", "Tomáš", + "Doležel", new Address(), List.of(), List.of()); + private final Lecture lecture = new Lecture( + LocalDateTime.now().plusDays(2), + LocalDateTime.now().plusDays(2).plusHours(2), + "Learning how to spell deprecated", + 10, + course, lecturer, new ArrayList<>(List.of())); + + private final User user = new User("novakovat", UserType.STUDENT, + "novakova@gamil.com", "password", "Tereza", + "Nováková", new Address(), List.of(), List.of()); + + private final Lecture lectureWithEnrolledStudent = new Lecture( + LocalDateTime.now().plusDays(2), + LocalDateTime.now().plusDays(2).plusHours(2), + "Learning how to spell deprecated", + 10, + course, lecturer, new ArrayList<>(List.of(student))); + private final List<Lecture> lectures = new ArrayList<>(List.of(lecture, lecture)); + + @Test + void save() { + when(lectureRepository.save(lecture)).thenReturn(lecture); + + Lecture result = lectureService.save(lecture); + + Assertions.assertEquals(lecture, result); + verify(lectureRepository).save(lecture); + } + + @Test + void notFoundById() { + when(lectureRepository.findById(anyLong())).thenReturn(Optional.empty()); + + Assertions.assertThrows(ResponseStatusException.class, () -> lectureService.findById(anyLong())); + + } + + @Test + void findById() { + when(lectureRepository.findById(anyLong())).thenReturn(Optional.of(lecture)); + + Lecture result = lectureService.findById(anyLong()); + + Assertions.assertEquals(lecture, result); + verify(lectureRepository).findById(anyLong()); + } + + @Test + void update() { + Long id = 1L; + when(lectureRepository.findById(anyLong())).thenReturn(Optional.of(lecture)); + when(lectureRepository.save(lecture)).thenReturn(lecture); + + Lecture result = lectureService.update(id, lecture); + + Assertions.assertEquals(lecture, result); + verify(lectureRepository).findById(anyLong()); + verify(lectureRepository).save(lecture); + } + + @Test + void updateIdDoesNotExist() { + Long id = 1L; + when(lectureRepository.findById(anyLong())).thenReturn(Optional.empty()); + + Assertions.assertThrows(ResponseStatusException.class, () -> lectureService.update(id, lecture)); + } + + @Test + void delete() { + Long id = 1L; + lectureService.delete(id); + + verify(lectureRepository).deleteById(id); + } + + @Test + void findAllByLanguage() { + Language language = Language.ENGLISH; + when(lectureRepository.findAllByLang(any(Language.class))).thenReturn(lectures); + + List<Lecture> result = lectureService.findAll(language); + + Assertions.assertEquals(lectures, result); + verify(lectureRepository).findAllByLang(language); + } + + @Test + void findAllByLanguageAndProf() { + Language language = Language.ENGLISH; + ProficiencyLevel proficiencyLevel = ProficiencyLevel.B1; + + when(lectureRepository.findAllByLangProf(any(Language.class), any(ProficiencyLevel.class))).thenReturn(lectures); + + List<Lecture> result = lectureService.findAll(language, proficiencyLevel); + + Assertions.assertEquals(lectures, result); + verify(lectureRepository).findAllByLangProf(language, proficiencyLevel); + } + + @Test + void enrol() { + Long id = 1L; + when(lectureRepository.findById(anyLong())).thenReturn(Optional.of(lecture)); + when(lectureRepository.save(any(Lecture.class))).thenReturn(lectureWithEnrolledStudent); + + Lecture result = lectureService.enrol(id, user); + + Assertions.assertEquals(lectureWithEnrolledStudent, result); + verify(lectureRepository).findById(id); + verify(lectureRepository).save(any(Lecture.class)); + } + + @Test + void enrolIdDoesNotExist() { + Long id = 1L; + when(lectureRepository.findById(anyLong())).thenReturn(Optional.empty()); + + Assertions.assertThrows(ResponseStatusException.class, () -> lectureService.enrol(id, user)); + } + + @Test + void expel() { + Long id = 1L; + when(lectureRepository.findById(anyLong())).thenReturn(Optional.of(lectureWithEnrolledStudent)); + when(lectureRepository.save(any(Lecture.class))).thenReturn(lecture); + + Lecture result = lectureService.expel(id, user); + + Assertions.assertEquals(lecture, result); + verify(lectureRepository).findById(id); + verify(lectureRepository).save(any(Lecture.class)); + } + + @Test + void expelIdDoesNotExist() { + Long id = 1L; + when(lectureRepository.findById(anyLong())).thenReturn(Optional.empty()); + + Assertions.assertThrows(ResponseStatusException.class, () -> lectureService.expel(id, user)); + } +}