diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000..faae30a --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,15 @@ +name: Test + +on: [ workflow_dispatch, push ] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + - name: Run the Maven verify phase + run: mvn --batch-mode --update-snapshots verify \ No newline at end of file diff --git a/pom.xml b/pom.xml index 30b6f83..a2d1e70 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent - 3.2.1 + 3.2.2 com.sfeir-open-source @@ -52,6 +52,10 @@ + + com.h2database + h2 + org.projectlombok lombok diff --git a/src/main/java/com/sfeiropensource/schoolapp/controller/SchoolController.java b/src/main/java/com/sfeiropensource/schoolapp/controller/SchoolController.java index 9fa0a3b..be31c41 100644 --- a/src/main/java/com/sfeiropensource/schoolapp/controller/SchoolController.java +++ b/src/main/java/com/sfeiropensource/schoolapp/controller/SchoolController.java @@ -9,6 +9,7 @@ import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; import org.springframework.http.HttpStatus; @@ -20,6 +21,7 @@ @Slf4j @RestController @CrossOrigin("*") +@RequiredArgsConstructor @RequestMapping("schools") @SecurityRequirement(name = "bearer-key") @Tag(name = "School", description = "School controller") @@ -27,10 +29,6 @@ public class SchoolController implements ExceptionInterceptor { private final SchoolService schoolService; - SchoolController(SchoolService schoolService) { - this.schoolService = schoolService; - } - /** * Retrieve all schools from database * diff --git a/src/main/java/com/sfeiropensource/schoolapp/exception/AlreadyExistException.java b/src/main/java/com/sfeiropensource/schoolapp/exception/AlreadyExistException.java deleted file mode 100644 index 81b272d..0000000 --- a/src/main/java/com/sfeiropensource/schoolapp/exception/AlreadyExistException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.sfeiropensource.schoolapp.exception; - -public class AlreadyExistException extends Exception { - public AlreadyExistException(String message) { - super(message); - } -} diff --git a/src/main/java/com/sfeiropensource/schoolapp/mapper/ObjectMapper.java b/src/main/java/com/sfeiropensource/schoolapp/mapper/ObjectMapper.java index 1f9f9c3..2d49717 100644 --- a/src/main/java/com/sfeiropensource/schoolapp/mapper/ObjectMapper.java +++ b/src/main/java/com/sfeiropensource/schoolapp/mapper/ObjectMapper.java @@ -10,10 +10,10 @@ @Mapper( componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE, - nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, + nullValueCheckStrategy = NullValueCheckStrategy.ON_IMPLICIT_CONVERSION, nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, - nullValueIterableMappingStrategy = NullValueMappingStrategy.RETURN_NULL, - nullValueMapMappingStrategy = NullValueMappingStrategy.RETURN_NULL, + nullValueIterableMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT, + nullValueMapMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT, nullValueMappingStrategy = NullValueMappingStrategy.RETURN_NULL ) public interface ObjectMapper { diff --git a/src/main/java/com/sfeiropensource/schoolapp/service/SchoolService.java b/src/main/java/com/sfeiropensource/schoolapp/service/SchoolService.java index e76faba..e518515 100644 --- a/src/main/java/com/sfeiropensource/schoolapp/service/SchoolService.java +++ b/src/main/java/com/sfeiropensource/schoolapp/service/SchoolService.java @@ -100,11 +100,11 @@ public ResponseEntity> search(int pageNumber, int pageSize, Sear /** * Update school inside the DB * - * @param id int - * @param schoolDTO CreateSchoolDTO + * @param id int + * @param createSchoolDTO CreateSchoolDTO * @return ResponseEntityD */ - public ResponseEntity update(String id, CreateSchoolDTO schoolDTO) throws NotFoundException { + public ResponseEntity update(String id, CreateSchoolDTO createSchoolDTO) throws NotFoundException { Optional request = schoolRepository.findById(id); if (request.isEmpty()) { throw new NotFoundException("No School is attached to this id"); @@ -113,7 +113,7 @@ public ResponseEntity update(String id, CreateSchoolDTO schoolDTO) th School school = request.get(); // Update school from dto. - objectMapper.updateSchoolFromSchoolDto(schoolDTO, school); + objectMapper.updateSchoolFromSchoolDto(createSchoolDTO, school); schoolRepository.save(school); diff --git a/src/test/java/com/sfeiropensource/schoolapp/controller/SchoolControllerTest.java b/src/test/java/com/sfeiropensource/schoolapp/controller/SchoolControllerTest.java new file mode 100644 index 0000000..2298761 --- /dev/null +++ b/src/test/java/com/sfeiropensource/schoolapp/controller/SchoolControllerTest.java @@ -0,0 +1,110 @@ +package com.sfeiropensource.schoolapp.controller; + +import com.sfeiropensource.schoolapp.exception.NotFoundException; +import com.sfeiropensource.schoolapp.model.CreateSchoolDTO; +import com.sfeiropensource.schoolapp.model.SchoolDTO; +import com.sfeiropensource.schoolapp.model.SearchSchoolDTO; +import com.sfeiropensource.schoolapp.service.SchoolService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import java.util.List; + +import static com.sfeiropensource.schoolapp.utils.Objects.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.when; + +class SchoolControllerTest { + + @Mock + private SchoolService schoolService; + + @InjectMocks + private SchoolController schoolController; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + } + + @Test + void getAll() { + ResponseEntity> expectedResult = ResponseEntity.ok(List.of()); + + when(schoolService.getAll()).thenReturn(expectedResult); + + ResponseEntity> result = schoolController.getAll(); + + assertEquals(expectedResult, result); + } + + @Test + void search() { + int pageNumber = 0; + int pageSize = 10; + SearchSchoolDTO searchSchoolDTO = generateSearchSchoolDTO(); + ResponseEntity> expectedResult = ResponseEntity.ok(new PageImpl<>(List.of())); + + when(schoolService.search(pageNumber, pageSize, searchSchoolDTO)).thenReturn(expectedResult); + + ResponseEntity> result = schoolController.search(searchSchoolDTO, pageNumber, pageSize); + + assertEquals(expectedResult, result); + } + + @Test + void add() { + CreateSchoolDTO createSchoolDTO = generateCreateSchoolDTO(); + ResponseEntity expectedResult = ResponseEntity.ok(generateSchoolDTO()); + + when(schoolService.saveSchool(createSchoolDTO)).thenReturn(expectedResult); + + ResponseEntity result = schoolController.add(createSchoolDTO); + + assertEquals(expectedResult, result); + } + + @Test + void get() throws NotFoundException { + String id = "id"; + ResponseEntity expectedResult = ResponseEntity.ok(generateSchoolDTO()); + + when(schoolService.get(id)).thenReturn(expectedResult); + + ResponseEntity result = schoolController.get(id); + + assertEquals(expectedResult, result); + } + + @Test + void update() throws NotFoundException { + String id = "id"; + CreateSchoolDTO createSchoolDTO = generateCreateSchoolDTO(); + ResponseEntity expectedResult = ResponseEntity.ok(generateSchoolDTO()); + + when(schoolService.update(id, createSchoolDTO)).thenReturn(expectedResult); + + ResponseEntity result = schoolController.update(id, createSchoolDTO); + + assertEquals(expectedResult, result); + } + + @Test + void delete() { + String id = "id"; + ResponseEntity expectedResult = new ResponseEntity<>(HttpStatus.NO_CONTENT); + + when(schoolService.delete(id)).thenReturn(expectedResult); + + ResponseEntity result = schoolController.delete(id); + + assertEquals(expectedResult, result); + } +} \ No newline at end of file diff --git a/src/test/java/com/sfeiropensource/schoolapp/controller/UserControllerTest.java b/src/test/java/com/sfeiropensource/schoolapp/controller/UserControllerTest.java new file mode 100644 index 0000000..9cedd97 --- /dev/null +++ b/src/test/java/com/sfeiropensource/schoolapp/controller/UserControllerTest.java @@ -0,0 +1,110 @@ +package com.sfeiropensource.schoolapp.controller; + +import com.sfeiropensource.schoolapp.exception.NotFoundException; +import com.sfeiropensource.schoolapp.model.CreateUserDTO; +import com.sfeiropensource.schoolapp.model.SearchUserDTO; +import com.sfeiropensource.schoolapp.model.UserDTO; +import com.sfeiropensource.schoolapp.service.UserService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import java.util.List; + +import static com.sfeiropensource.schoolapp.utils.Objects.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.when; + +class UserControllerTest { + + @Mock + private UserService schoolService; + + @InjectMocks + private UserController schoolController; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + } + + @Test + void getAll() { + ResponseEntity> expectedResult = ResponseEntity.ok(List.of()); + + when(schoolService.getAll()).thenReturn(expectedResult); + + ResponseEntity> result = schoolController.getAll(); + + assertEquals(expectedResult, result); + } + + @Test + void search() { + int pageNumber = 0; + int pageSize = 10; + SearchUserDTO searchUserDTO = generateSearchUserDTO(); + ResponseEntity> expectedResult = ResponseEntity.ok(new PageImpl<>(List.of())); + + when(schoolService.search(pageNumber, pageSize, searchUserDTO)).thenReturn(expectedResult); + + ResponseEntity> result = schoolController.search(searchUserDTO, pageNumber, pageSize); + + assertEquals(expectedResult, result); + } + + @Test + void add() { + CreateUserDTO createUserDTO = generateCreateUserDTO(); + ResponseEntity expectedResult = ResponseEntity.ok(generateUserDTO()); + + when(schoolService.add(createUserDTO)).thenReturn(expectedResult); + + ResponseEntity result = schoolController.add(createUserDTO); + + assertEquals(expectedResult, result); + } + + @Test + void get() throws NotFoundException { + String id = "id"; + ResponseEntity expectedResult = ResponseEntity.ok(generateUserDTO()); + + when(schoolService.get(id)).thenReturn(expectedResult); + + ResponseEntity result = schoolController.get(id); + + assertEquals(expectedResult, result); + } + + @Test + void update() throws NotFoundException { + String id = "id"; + CreateUserDTO createUserDTO = generateCreateUserDTO(); + ResponseEntity expectedResult = ResponseEntity.ok(generateUserDTO()); + + when(schoolService.update(id, createUserDTO)).thenReturn(expectedResult); + + ResponseEntity result = schoolController.update(id, createUserDTO); + + assertEquals(expectedResult, result); + } + + @Test + void delete() { + String id = "id"; + ResponseEntity expectedResult = new ResponseEntity<>(HttpStatus.NO_CONTENT); + + when(schoolService.delete(id)).thenReturn(expectedResult); + + ResponseEntity result = schoolController.delete(id); + + assertEquals(expectedResult, result); + } +} \ No newline at end of file diff --git a/src/test/java/com/sfeiropensource/schoolapp/mapper/ObjectMapperTest.java b/src/test/java/com/sfeiropensource/schoolapp/mapper/ObjectMapperTest.java new file mode 100644 index 0000000..e0f052c --- /dev/null +++ b/src/test/java/com/sfeiropensource/schoolapp/mapper/ObjectMapperTest.java @@ -0,0 +1,242 @@ +package com.sfeiropensource.schoolapp.mapper; + +import com.sfeiropensource.schoolapp.entity.School; +import com.sfeiropensource.schoolapp.entity.User; +import com.sfeiropensource.schoolapp.model.*; +import org.junit.jupiter.api.Test; +import org.mapstruct.factory.Mappers; + +import java.util.ArrayList; +import java.util.List; + +import static com.sfeiropensource.schoolapp.utils.Objects.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +class ObjectMapperTest { + + private final ObjectMapper objectMapper = Mappers.getMapper(ObjectMapper.class); + + @Test + void toSchoolDTO() { + School school = generateSchool(); + + SchoolDTO expectedResult = generateSchoolDTO(); + + SchoolDTO result = objectMapper.toSchoolDTO(school); + + assertEquals(expectedResult, result); + assertNull(objectMapper.toSchoolDTO(null)); + + // If no teachers are present, it must create a new empty array list. + school.setTeachers(null); + expectedResult.setTeachers(new ArrayList<>()); + + result = objectMapper.toSchoolDTO(school); + + assertEquals(expectedResult, result); + } + + @Test + void newSchool() { + CreateSchoolDTO createSchoolDTO = generateCreateSchoolDTO(); + + School expectedResult = generateSchool(); + expectedResult.setId(null); + expectedResult.setCreatedAt(null); + expectedResult.setCreatedBy(null); + expectedResult.setUpdatedAt(null); + expectedResult.setUpdatedBy(null); + expectedResult.setVersion(0); + + School result = objectMapper.newSchool(createSchoolDTO); + + assertEquals(expectedResult, result); + assertNull(objectMapper.newSchool(null)); + + // If no professor, it should return null for professor user object. + createSchoolDTO.setProfessor(null); + expectedResult.setProfessor(null); + + // If no teachers are present, it must create a new empty array list. + createSchoolDTO.setTeachers(null); + expectedResult.setTeachers(new ArrayList<>()); + + result = objectMapper.newSchool(createSchoolDTO); + + assertEquals(expectedResult, result); + } + + @Test + void toUserDTO() { + User user = generateUser(); + + UserDTO expectedResult = generateUserDTO(); + + UserDTO result = objectMapper.toUserDTO(user); + + assertEquals(expectedResult, result); + assertNull(objectMapper.toUserDTO(null)); + } + + @Test + void newUser() { + CreateUserDTO createUserDTO = generateCreateUserDTO(); + + User expectedResult = generateUser(); + expectedResult.setId(null); + expectedResult.setCreatedAt(null); + expectedResult.setCreatedBy(null); + expectedResult.setUpdatedAt(null); + expectedResult.setUpdatedBy(null); + expectedResult.setVersion(0); + + User result = objectMapper.newUser(createUserDTO); + + assertEquals(expectedResult, result); + assertNull(objectMapper.newUser(null)); + } + + @Test + void updateSchoolFromSchoolDto() { + CreateSchoolDTO createSchoolDTO = generateCreateSchoolDTO(); + School result = School.builder().build(); + + School expectedResult = generateSchool(); + expectedResult.setId(null); + expectedResult.setCreatedAt(null); + expectedResult.setCreatedBy(null); + expectedResult.setUpdatedAt(null); + expectedResult.setUpdatedBy(null); + expectedResult.setVersion(0); + + objectMapper.updateSchoolFromSchoolDto(createSchoolDTO, result); + + assertEquals(expectedResult, result); + + expectedResult = generateSchool(); + result = generateSchool(); + + objectMapper.updateSchoolFromSchoolDto(createSchoolDTO, result); + + assertEquals(expectedResult, result); + } + + @Test + void updateUserFromUserDto() { + CreateUserDTO createUserDTO = generateCreateUserDTO(); + User result = User.builder().build(); + + User expectedResult = generateUser(); + expectedResult.setId(null); + expectedResult.setCreatedAt(null); + expectedResult.setCreatedBy(null); + expectedResult.setUpdatedAt(null); + expectedResult.setUpdatedBy(null); + expectedResult.setVersion(0); + + objectMapper.updateUserFromUserDto(createUserDTO, result); + + assertEquals(expectedResult, result); + + expectedResult = generateUser(); + result = generateUser(); + + objectMapper.updateUserFromUserDto(createUserDTO, result); + + assertEquals(expectedResult, result); + } + + @Test + void constructExample() { + SearchSchoolDTO searchSchoolDTO = generateSearchSchoolDTO(); + School expectedResult = generateSchool(); + + expectedResult.setId(null); + expectedResult.setImage(null); + expectedResult.setCreatedAt(null); + expectedResult.setCreatedBy(null); + expectedResult.setUpdatedAt(null); + expectedResult.setUpdatedBy(null); + expectedResult.setVersion(0); + + expectedResult.getProfessor().setId(null); + expectedResult.getProfessor().setCreatedAt(null); + expectedResult.getProfessor().setCreatedBy(null); + expectedResult.getProfessor().setUpdatedAt(null); + expectedResult.getProfessor().setUpdatedBy(null); + expectedResult.getProfessor().setVersion(0); + + expectedResult.getTeachers().get(0).setId(null); + expectedResult.getTeachers().get(0).setCreatedAt(null); + expectedResult.getTeachers().get(0).setCreatedBy(null); + expectedResult.getTeachers().get(0).setUpdatedAt(null); + expectedResult.getTeachers().get(0).setUpdatedBy(null); + expectedResult.getTeachers().get(0).setVersion(0); + + School result = objectMapper.constructExample(searchSchoolDTO); + + assertEquals(expectedResult, result); + + assertNull(objectMapper.constructExample((SearchSchoolDTO) null)); + } + + @Test + void map() { + String value = "value"; + + List expectedResult = List.of(value); + + List result = objectMapper.map(value); + + assertEquals(expectedResult, result); + + expectedResult = List.of(); + result = objectMapper.map((String) null); + + assertEquals(expectedResult, result); + } + + @Test + void testConstructExample() { + SearchUserDTO searchUserDTO = generateSearchUserDTO(); + User expectedResult = generateUser(); + + expectedResult.setId(null); + expectedResult.setCreatedAt(null); + expectedResult.setCreatedBy(null); + expectedResult.setUpdatedAt(null); + expectedResult.setUpdatedBy(null); + expectedResult.setVersion(0); + + User result = objectMapper.constructExample(searchUserDTO); + + assertEquals(expectedResult, result); + + assertNull(objectMapper.constructExample((SearchUserDTO) null)); + } + + @Test + void testMap() { + SearchUserDTO value = generateSearchUserDTO(); + User user = generateUser(); + + user.setId(null); + user.setCreatedAt(null); + user.setCreatedBy(null); + user.setUpdatedAt(null); + user.setUpdatedBy(null); + user.setVersion(0); + + List expectedResult = List.of(user); + + List result = objectMapper.map(value); + + assertEquals(expectedResult, result); + + expectedResult = List.of(); + result = objectMapper.map((SearchUserDTO) null); + + assertEquals(expectedResult, result); + } +} \ No newline at end of file diff --git a/src/test/java/com/sfeiropensource/schoolapp/service/SchoolServiceTest.java b/src/test/java/com/sfeiropensource/schoolapp/service/SchoolServiceTest.java new file mode 100644 index 0000000..4ac9294 --- /dev/null +++ b/src/test/java/com/sfeiropensource/schoolapp/service/SchoolServiceTest.java @@ -0,0 +1,170 @@ +package com.sfeiropensource.schoolapp.service; + +import com.sfeiropensource.schoolapp.entity.School; +import com.sfeiropensource.schoolapp.exception.NotFoundException; +import com.sfeiropensource.schoolapp.mapper.ObjectMapper; +import com.sfeiropensource.schoolapp.mapper.ObjectMapperImpl; +import com.sfeiropensource.schoolapp.model.CreateSchoolDTO; +import com.sfeiropensource.schoolapp.model.SchoolDTO; +import com.sfeiropensource.schoolapp.model.SearchSchoolDTO; +import com.sfeiropensource.schoolapp.repository.SchoolRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.data.domain.Example; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Optional; + +import static com.sfeiropensource.schoolapp.utils.Objects.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +class SchoolServiceTest { + @Mock + private SchoolRepository schoolRepository; + + @Mock + private ObjectMapper objectMapper = new ObjectMapperImpl(); + + @InjectMocks + private SchoolService schoolService; + + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + } + + + @Test + void saveSchool() { + CreateSchoolDTO createSchoolDTO = generateCreateSchoolDTO(); + SchoolDTO schoolDTO = generateSchoolDTO(); + School school = generateSchool(); + + when(schoolRepository.save(school)).thenReturn(school); + when(objectMapper.newSchool(createSchoolDTO)).thenReturn(school); + when(objectMapper.toSchoolDTO(school)).thenReturn(schoolDTO); + + ResponseEntity expectedResult = ResponseEntity + .status(HttpStatus.CREATED) + .body(schoolDTO); + + ResponseEntity result = this.schoolService.saveSchool(createSchoolDTO); + + assertEquals(expectedResult, result); + } + + @Test + void get() throws NotFoundException { + String id = "id"; + School school = generateSchool(); + Optional optionalSchool = Optional.of(school); + SchoolDTO schoolDTO = generateSchoolDTO(); + + when(schoolRepository.findById(id)).thenReturn(optionalSchool); + when(objectMapper.toSchoolDTO(school)).thenReturn(schoolDTO); + + ResponseEntity expectedResult = ResponseEntity.ok(schoolDTO); + + ResponseEntity result = schoolService.get(id); + + assertEquals(expectedResult, result); + + String invalidId = "bad_id"; + when(schoolRepository.findById(invalidId)).thenReturn(Optional.empty()); + + assertThrows(NotFoundException.class, () -> schoolService.get(invalidId)); + } + + @Test + void getAll() { + School school = generateSchool(); + SchoolDTO schoolDTO = generateSchoolDTO(); + + when(schoolRepository.findAll()).thenReturn(List.of(school)); + when(objectMapper.toSchoolDTO(school)).thenReturn(schoolDTO); + + ResponseEntity> expectedResult = ResponseEntity.ok(List.of(schoolDTO)); + ResponseEntity> result = schoolService.getAll(); + + assertEquals(expectedResult, result); + } + + @Test + void search() { + int pageNumber = 0; + int pageSize = 10; + SearchSchoolDTO searchSchoolDTO = generateSearchSchoolDTO(); + School school = generateSchool(); + SchoolDTO schoolDTO = generateSchoolDTO(); + + Page page = new PageImpl<>(List.of(school)); + when(objectMapper.constructExample(searchSchoolDTO)).thenReturn(school); + when(schoolRepository.findAll(any(Example.class), any(Pageable.class))).thenReturn(page); + when(objectMapper.toSchoolDTO(school)).thenReturn(schoolDTO); + + ResponseEntity> expectedResult = ResponseEntity.ok(new PageImpl<>(List.of(schoolDTO))); + + ResponseEntity> result = schoolService.search(pageNumber, pageSize, searchSchoolDTO); + + assertEquals(expectedResult, result); + + } + + @Test + void update() throws NotFoundException { + String id = "id"; + School school = generateSchool(); + CreateSchoolDTO createSchoolDTO = generateCreateSchoolDTO(); + SchoolDTO schoolDTO = generateSchoolDTO(); + + when(schoolRepository.findById(id)).thenReturn(Optional.of(school)); + when(schoolRepository.save(school)).thenReturn(school); + when(objectMapper.toSchoolDTO(school)).thenReturn(schoolDTO); + + ResponseEntity expectedResult = ResponseEntity.ok(schoolDTO); + ResponseEntity result = schoolService.update(id, createSchoolDTO); + + verify(objectMapper).updateSchoolFromSchoolDto(createSchoolDTO, school); + verify(schoolRepository).save(school); + + assertEquals(expectedResult, result); + + String invalidId = "bad_id"; + when(schoolRepository.findById(invalidId)).thenReturn(Optional.empty()); + + assertThrows(NotFoundException.class, () -> schoolService.update(invalidId, createSchoolDTO)); + } + + @Test + void delete() { + String id = "id"; + + ResponseEntity expectedResult = new ResponseEntity<>(HttpStatus.NO_CONTENT); + ResponseEntity result = schoolService.delete(id); + + verify(schoolRepository).deleteById(id); + + assertEquals(expectedResult, result); + + doThrow(NoSuchElementException.class).when(schoolRepository).deleteById(id); + + expectedResult = new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + result = schoolService.delete(id); + + assertEquals(expectedResult, result); + } + +} \ No newline at end of file diff --git a/src/test/java/com/sfeiropensource/schoolapp/service/UserServiceTest.java b/src/test/java/com/sfeiropensource/schoolapp/service/UserServiceTest.java new file mode 100644 index 0000000..3f2b457 --- /dev/null +++ b/src/test/java/com/sfeiropensource/schoolapp/service/UserServiceTest.java @@ -0,0 +1,170 @@ +package com.sfeiropensource.schoolapp.service; + +import com.sfeiropensource.schoolapp.entity.User; +import com.sfeiropensource.schoolapp.exception.NotFoundException; +import com.sfeiropensource.schoolapp.mapper.ObjectMapper; +import com.sfeiropensource.schoolapp.mapper.ObjectMapperImpl; +import com.sfeiropensource.schoolapp.model.CreateUserDTO; +import com.sfeiropensource.schoolapp.model.SearchUserDTO; +import com.sfeiropensource.schoolapp.model.UserDTO; +import com.sfeiropensource.schoolapp.repository.UserRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.data.domain.Example; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Optional; + +import static com.sfeiropensource.schoolapp.utils.Objects.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +class UserServiceTest { + @Mock + private UserRepository userRepository; + + @Mock + private ObjectMapper objectMapper = new ObjectMapperImpl(); + + @InjectMocks + private UserService userService; + + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + } + + + @Test + void add() { + CreateUserDTO createUserDTO = generateCreateUserDTO(); + UserDTO userDTO = generateUserDTO(); + User user = generateUser(); + + when(userRepository.save(user)).thenReturn(user); + when(objectMapper.newUser(createUserDTO)).thenReturn(user); + when(objectMapper.toUserDTO(user)).thenReturn(userDTO); + + ResponseEntity expectedResult = ResponseEntity + .status(HttpStatus.CREATED) + .body(userDTO); + + ResponseEntity result = this.userService.add(createUserDTO); + + assertEquals(expectedResult, result); + } + + @Test + void get() throws NotFoundException { + String id = "id"; + User user = generateUser(); + Optional optionalUser = Optional.of(user); + UserDTO userDTO = generateUserDTO(); + + when(userRepository.findById(id)).thenReturn(optionalUser); + when(objectMapper.toUserDTO(user)).thenReturn(userDTO); + + ResponseEntity expectedResult = ResponseEntity.ok(userDTO); + + ResponseEntity result = userService.get(id); + + assertEquals(expectedResult, result); + + String invalidId = "bad_id"; + when(userRepository.findById(invalidId)).thenReturn(Optional.empty()); + + assertThrows(NotFoundException.class, () -> userService.get(invalidId)); + } + + @Test + void getAll() { + User user = generateUser(); + UserDTO userDTO = generateUserDTO(); + + when(userRepository.findAll()).thenReturn(List.of(user)); + when(objectMapper.toUserDTO(user)).thenReturn(userDTO); + + ResponseEntity> expectedResult = ResponseEntity.ok(List.of(userDTO)); + ResponseEntity> result = userService.getAll(); + + assertEquals(expectedResult, result); + } + + @Test + void search() { + int pageNumber = 0; + int pageSize = 10; + SearchUserDTO searchUserDTO = generateSearchUserDTO(); + User user = generateUser(); + UserDTO userDTO = generateUserDTO(); + + Page page = new PageImpl<>(List.of(user)); + when(objectMapper.constructExample(searchUserDTO)).thenReturn(user); + when(userRepository.findAll(any(Example.class), any(Pageable.class))).thenReturn(page); + when(objectMapper.toUserDTO(user)).thenReturn(userDTO); + + ResponseEntity> expectedResult = ResponseEntity.ok(new PageImpl<>(List.of(userDTO))); + + ResponseEntity> result = userService.search(pageNumber, pageSize, searchUserDTO); + + assertEquals(expectedResult, result); + + } + + @Test + void update() throws NotFoundException { + String id = "id"; + User user = generateUser(); + CreateUserDTO createUserDTO = generateCreateUserDTO(); + UserDTO userDTO = generateUserDTO(); + + when(userRepository.findById(id)).thenReturn(Optional.of(user)); + when(userRepository.save(user)).thenReturn(user); + when(objectMapper.toUserDTO(user)).thenReturn(userDTO); + + ResponseEntity expectedResult = ResponseEntity.ok(userDTO); + ResponseEntity result = userService.update(id, createUserDTO); + + verify(objectMapper).updateUserFromUserDto(createUserDTO, user); + verify(userRepository).save(user); + + assertEquals(expectedResult, result); + + String invalidId = "bad_id"; + when(userRepository.findById(invalidId)).thenReturn(Optional.empty()); + + assertThrows(NotFoundException.class, () -> userService.update(invalidId, createUserDTO)); + } + + @Test + void delete() { + String id = "id"; + + ResponseEntity expectedResult = new ResponseEntity<>(HttpStatus.NO_CONTENT); + ResponseEntity result = userService.delete(id); + + verify(userRepository).deleteById(id); + + assertEquals(expectedResult, result); + + doThrow(NoSuchElementException.class).when(userRepository).deleteById(id); + + expectedResult = new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + result = userService.delete(id); + + assertEquals(expectedResult, result); + } + +} \ No newline at end of file diff --git a/src/test/java/com/sfeiropensource/schoolapp/utils/Objects.java b/src/test/java/com/sfeiropensource/schoolapp/utils/Objects.java new file mode 100644 index 0000000..1973dae --- /dev/null +++ b/src/test/java/com/sfeiropensource/schoolapp/utils/Objects.java @@ -0,0 +1,133 @@ +package com.sfeiropensource.schoolapp.utils; + +import com.sfeiropensource.schoolapp.entity.School; +import com.sfeiropensource.schoolapp.entity.User; +import com.sfeiropensource.schoolapp.model.*; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; + +public class Objects { + public static SearchSchoolDTO generateSearchSchoolDTO() { + return SearchSchoolDTO.builder() + .title("title") + .publicSummary("publicSummary") + .duration("duration") + .objectives("objectives") + .prerequisites("prerequisites") + .document("document") + .githubLink("githubLink") + .user(generateSearchUserDTO()) + .status("status") + .build(); + } + + public static SearchUserDTO generateSearchUserDTO() { + return SearchUserDTO.builder() + .firstname("firstname") + .lastname("lastname") + .email("email") + .role("role") + .build(); + } + + public static CreateSchoolDTO generateCreateSchoolDTO() { + return CreateSchoolDTO.builder() + .title("title") + .image("image") + .publicSummary("publicSummary") + .duration("duration") + .objectives(new ArrayList<>(List.of("objectives"))) + .prerequisites(new ArrayList<>(List.of("prerequisites"))) + .document("document") + .githubLink("githubLink") + .teachers(new ArrayList<>(List.of(generateUserDTO()))) + .professor(generateUserDTO()) + .status("status") + .build(); + } + + public static SchoolDTO generateSchoolDTO() { + return SchoolDTO.builder() + .id("id") + .title("title") + .image("image") + .publicSummary("publicSummary") + .duration("duration") + .objectives(new ArrayList<>(List.of("objectives"))) + .prerequisites(new ArrayList<>(List.of("prerequisites"))) + .document("document") + .githubLink("githubLink") + .teachers(new ArrayList<>(List.of(generateUserDTO()))) + .professor(generateUserDTO()) + .status("status") + .createdBy("createdBy") + .createdAt(Instant.EPOCH) + .updatedBy("createdBy") + .updatedAt(Instant.EPOCH) + .version(1) + .build(); + } + + public static CreateUserDTO generateCreateUserDTO() { + return CreateUserDTO.builder() + .firstname("firstname") + .lastname("lastname") + .email("email") + .role("role") + .build(); + } + + public static UserDTO generateUserDTO() { + return UserDTO.builder() + .id("id") + .firstname("firstname") + .lastname("lastname") + .email("email") + .role("role") + .createdBy("createdBy") + .createdAt(Instant.EPOCH) + .updatedBy("createdBy") + .updatedAt(Instant.EPOCH) + .version(1) + .build(); + } + + public static School generateSchool() { + return School.builder() + .id("id") + .title("title") + .image("image") + .publicSummary("publicSummary") + .duration("duration") + .objectives(new ArrayList<>(List.of("objectives"))) + .prerequisites(new ArrayList<>(List.of("prerequisites"))) + .document("document") + .githubLink("githubLink") + .teachers(new ArrayList<>(List.of(generateUser()))) + .professor(generateUser()) + .status("status") + .createdBy("createdBy") + .createdAt(Instant.EPOCH) + .updatedBy("createdBy") + .updatedAt(Instant.EPOCH) + .version(1) + .build(); + } + + public static User generateUser() { + return User.builder() + .id("id") + .firstname("firstname") + .lastname("lastname") + .email("email") + .role("role") + .createdBy("createdBy") + .createdAt(Instant.EPOCH) + .updatedBy("createdBy") + .updatedAt(Instant.EPOCH) + .version(1) + .build(); + } +} diff --git a/src/test/java/com/sfeiropensource/schoolapp/utils/UserAuditTest.java b/src/test/java/com/sfeiropensource/schoolapp/utils/UserAuditTest.java new file mode 100644 index 0000000..4f4779f --- /dev/null +++ b/src/test/java/com/sfeiropensource/schoolapp/utils/UserAuditTest.java @@ -0,0 +1,28 @@ +package com.sfeiropensource.schoolapp.utils; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.MockitoAnnotations; + +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class UserAuditTest { + + @InjectMocks + private UserAudit userAudit; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + } + + @Test + void getCurrentAuditor() { + Optional expectedResult = Optional.of("auditor"); + + assertEquals(expectedResult, this.userAudit.getCurrentAuditor()); + } +} \ No newline at end of file