diff --git a/README.md b/README.md index 8ca11f4..7def7ff 100644 --- a/README.md +++ b/README.md @@ -257,6 +257,7 @@ Update an existing user's information. ```http PUT /random-users/1 Content-Type: application/json +PUT /random-users/{id} ``` **Request Body:** @@ -272,6 +273,24 @@ Content-Type: application/json "nat": "FR" } ``` +#### Create a new user +```http +POST /random-users +``` +Example body: + +```json +{ + "gender": "female", + "firstname": "Albert", + "lastname": "Bing", + "civility": "Mrs", + "email": "albert.bing@example.com", + "phone": "123456789", + "picture": "pic.jpg", + "nat": "FR" +} +``` **Responses:** - `200 OK` - User updated successfully @@ -567,7 +586,7 @@ This project integrates with **Random User Generator API**: - [x] [Add this endpoint get /user/{id}](https://github.com/XPEHO/spring_boot_java_random_user/issues/8) - [x] [Add this endpoint put /user/{id}](https://github.com/XPEHO/spring_boot_java_random_user/issues/9) - [ ] [Add this endpoint delete /user/{id}](https://github.com/XPEHO/spring_boot_java_random_user/issues/10) -- [ ] [Add this endpoint post /user](https://github.com/XPEHO/spring_boot_java_random_user/issues/11) +- [x] [Add this endpoint post /user](https://github.com/XPEHO/spring_boot_java_random_user/issues/11) --- diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/CreateUserUseCase.java b/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/CreateUserUseCase.java new file mode 100644 index 0000000..7046cdf --- /dev/null +++ b/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/CreateUserUseCase.java @@ -0,0 +1,31 @@ +package com.xpeho.spring_boot_java_random_user.domain.usecases; + +import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity; +import com.xpeho.spring_boot_java_random_user.domain.entities.UserRequest; +import com.xpeho.spring_boot_java_random_user.domain.services.UserService; +import org.springframework.stereotype.Service; + +@Service +public class CreateUserUseCase { + private final UserService userService; + + public CreateUserUseCase(UserService userService) { + this.userService = userService; + } + + public UserEntity execute(UserRequest user) { + UserEntity userToCreate = new UserEntity( + null, + user.gender(), + user.firstname(), + user.lastname(), + user.civility(), + user.email(), + user.phone(), + user.picture(), + user.nat() + ); + + return userService.save(userToCreate); + } +} diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/controllers/UserController.java b/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/controllers/UserController.java index c8ad32a..c5c7933 100644 --- a/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/controllers/UserController.java +++ b/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/controllers/UserController.java @@ -9,6 +9,7 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -76,4 +77,16 @@ ResponseEntity updateRandomUser( @RequestBody UserRequest user ); + + @PostMapping("") + @Operation( + summary = "Create a user", + description = "Creates a new user in the database.", + parameters = { + @Parameter(name = "UserRequest", description = "User data to persist") + } + ) + @ApiResponse(responseCode = "201", description = "User successfully created") + @ApiResponse(responseCode = "500", description = "Internal server error") + ResponseEntity createUser(@RequestBody UserRequest user); } diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/handlers/UserHandler.java b/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/handlers/UserHandler.java index 6bb260f..b97b925 100644 --- a/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/handlers/UserHandler.java +++ b/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/handlers/UserHandler.java @@ -3,6 +3,7 @@ import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity; import com.xpeho.spring_boot_java_random_user.domain.entities.UserRequest; import com.xpeho.spring_boot_java_random_user.domain.exceptions.UserNotFoundException; +import com.xpeho.spring_boot_java_random_user.domain.usecases.CreateUserUseCase; import com.xpeho.spring_boot_java_random_user.domain.usecases.FetchAndSaveRandomUsersUseCase; import com.xpeho.spring_boot_java_random_user.domain.usecases.GetUserByIdUseCase; import com.xpeho.spring_boot_java_random_user.domain.usecases.UpdateRandomUserUseCase; @@ -11,6 +12,7 @@ import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import java.io.IOException; @@ -26,16 +28,21 @@ public class UserHandler implements UserController { private final FetchAndSaveRandomUsersUseCase fetchAndSaveRandomUsersUseCase; private final UpdateRandomUserUseCase updateRandomUserUseCase; private final GetUserByIdUseCase getUserByIdUseCase; + private final CreateUserUseCase createUserUseCase; public UserHandler( FetchAndSaveRandomUsersUseCase fetchAndSaveRandomUsersUseCase, UpdateRandomUserUseCase updateRandomUserUseCase, - GetUserByIdUseCase getUserByIdUseCase + GetUserByIdUseCase getUserByIdUseCase, + CreateUserUseCase createUserUseCase ) { this.fetchAndSaveRandomUsersUseCase = fetchAndSaveRandomUsersUseCase; this.updateRandomUserUseCase = updateRandomUserUseCase; this.getUserByIdUseCase = getUserByIdUseCase; + this.createUserUseCase = createUserUseCase; + } + @Override public ResponseEntity> getRandomUsers(int count) { @@ -59,15 +66,21 @@ public ResponseEntity updateRandomUser(int id, UserRequest user) { } } - @Override - public ResponseEntity getUserById(int id) { - try { - UserEntity user = getUserByIdUseCase.execute(id); - return ResponseEntity.ok(user); - } catch (UserNotFoundException e) { - logger.warn("warning: the requested user does not exist : {}", e.getMessage(), e); - return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); - } + @Override + public ResponseEntity getUserById(int id) { + try { + UserEntity user = getUserByIdUseCase.execute(id); + return ResponseEntity.ok(user); + } catch (UserNotFoundException e) { + logger.warn("warning: the requested user does not exist : {}", e.getMessage(), e); + return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); } + } + + @Override + public ResponseEntity createUser(@RequestBody UserRequest user) { + UserEntity createdUser = createUserUseCase.execute(user); + return ResponseEntity.status(HttpStatus.CREATED).body(createdUser); + } } diff --git a/src/test/java/com/xpeho/spring_boot_java_random_user/data/services/UserServiceImplTest.java b/src/test/java/com/xpeho/spring_boot_java_random_user/data/services/UserServiceImplTest.java index 2b86838..e99b1b2 100644 --- a/src/test/java/com/xpeho/spring_boot_java_random_user/data/services/UserServiceImplTest.java +++ b/src/test/java/com/xpeho/spring_boot_java_random_user/data/services/UserServiceImplTest.java @@ -65,7 +65,6 @@ void shouldSaveMappedUserAndReturnMappedDomainEntity() { UserEntity input = new UserEntity(3L, "female", "Alice", "Smith", "Mrs", "alice@smith.com", "5678", "new-pic.jpg", "US"); User daoToSave = new User(); - daoToSave.setId(3L); daoToSave.setFirstname("Alice"); User savedDao = new User(); diff --git a/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/CreateUserUseCaseTest.java b/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/CreateUserUseCaseTest.java new file mode 100644 index 0000000..9a44e26 --- /dev/null +++ b/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/CreateUserUseCaseTest.java @@ -0,0 +1,45 @@ +package com.xpeho.spring_boot_java_random_user.domain.usecases; + +import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity; +import com.xpeho.spring_boot_java_random_user.domain.entities.UserRequest; +import com.xpeho.spring_boot_java_random_user.domain.services.UserService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +class CreateUserUseCaseTest { + private UserService userService; + private CreateUserUseCase useCase; + + @BeforeEach + void setUp() { + userService = mock(UserService.class); + useCase = new CreateUserUseCase(userService); + } + + @Test + @DisplayName("Should create a user without keeping the input id") + void shouldCreateUserWithoutKeepingInputId() { + UserRequest payload = new UserRequest( + "female", "Alice", "Smith", "Mrs", "alice@smith.com", "5678", "new-pic.jpg", "US" + ); + UserEntity createdUser = new UserEntity( + 1L, "female", "Alice", "Smith", "Mrs", "alice@smith.com", "5678", "new-pic.jpg", "US" + ); + UserEntity expectedSavedUser = new UserEntity( + null, "female", "Alice", "Smith", "Mrs", "alice@smith.com", "5678", "new-pic.jpg", "US" + ); + + when(userService.save(expectedSavedUser)).thenReturn(createdUser); + + UserEntity result = useCase.execute(payload); + + assertEquals(createdUser, result); + verify(userService).save(expectedSavedUser); + } +} diff --git a/src/test/java/com/xpeho/spring_boot_java_random_user/presentation/UserHandlerTest.java b/src/test/java/com/xpeho/spring_boot_java_random_user/presentation/UserHandlerTest.java index 8debcad..fa4663e 100644 --- a/src/test/java/com/xpeho/spring_boot_java_random_user/presentation/UserHandlerTest.java +++ b/src/test/java/com/xpeho/spring_boot_java_random_user/presentation/UserHandlerTest.java @@ -3,6 +3,7 @@ import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity; import com.xpeho.spring_boot_java_random_user.domain.entities.UserRequest; import com.xpeho.spring_boot_java_random_user.domain.exceptions.UserNotFoundException; +import com.xpeho.spring_boot_java_random_user.domain.usecases.CreateUserUseCase; import com.xpeho.spring_boot_java_random_user.domain.usecases.FetchAndSaveRandomUsersUseCase; import com.xpeho.spring_boot_java_random_user.domain.usecases.GetUserByIdUseCase; import com.xpeho.spring_boot_java_random_user.domain.usecases.UpdateRandomUserUseCase; @@ -29,6 +30,7 @@ class UserHandlerTest { private FetchAndSaveRandomUsersUseCase fetchAndSaveRandomUsersUseCase; private UpdateRandomUserUseCase updateRandomUserUseCase; private GetUserByIdUseCase getUserByIdUseCase; + private CreateUserUseCase createUserUseCase; private UserHandler userHandler; @BeforeEach @@ -36,7 +38,8 @@ void setUp() { fetchAndSaveRandomUsersUseCase = mock(FetchAndSaveRandomUsersUseCase.class); updateRandomUserUseCase = mock(UpdateRandomUserUseCase.class); getUserByIdUseCase = mock(GetUserByIdUseCase.class); - userHandler = new UserHandler(fetchAndSaveRandomUsersUseCase, updateRandomUserUseCase, getUserByIdUseCase); + createUserUseCase = mock(CreateUserUseCase.class); + userHandler = new UserHandler(fetchAndSaveRandomUsersUseCase, updateRandomUserUseCase, getUserByIdUseCase, createUserUseCase); } @Test @@ -117,4 +120,18 @@ void shouldReturnNotFoundWhenUpdateRandomUserFails() { assertNull(response.getBody()); verify(updateRandomUserUseCase, times(1)).execute(123, request); } + + @Test + @DisplayName("Should return 201 and created user when createUser succeeds") + void shouldReturnCreatedWhenCreateUserSucceeds() { + UserRequest request = new UserRequest("female", "Emma", "Stone", "Ms", "emma@example.com", "0644444444", "emma.jpg", "FR"); + UserEntity created = new UserEntity(10L, "female", "Emma", "Stone", "Ms", "emma@example.com", "0644444444", "emma.jpg", "FR"); + when(createUserUseCase.execute(request)).thenReturn(created); + + ResponseEntity response = userHandler.createUser(request); + + assertEquals(HttpStatus.CREATED, response.getStatusCode()); + assertEquals(created, response.getBody()); + verify(createUserUseCase, times(1)).execute(request); + } }