diff --git a/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java b/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java index 083d64a5b..38fa09194 100644 --- a/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java +++ b/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java @@ -11,12 +11,18 @@ public enum ErrorCode implements ResponseCode { API_METHOD_NOT_ALLOWED(HttpStatus.METHOD_NOT_ALLOWED, 40500, "허용되지 않는 HTTP 메소드입니다."), API_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 50000, "서버 내부 오류입니다."), - API_BAD_REQUEST(HttpStatus.BAD_REQUEST, 40002, "잘못된 요청입니다."), + API_BAD_REQUEST(HttpStatus.BAD_REQUEST, 40000, "잘못된 요청입니다."), API_MISSING_PARAM(HttpStatus.BAD_REQUEST, 40001, "필수 파라미터가 없습니다."), API_INVALID_PARAM(HttpStatus.BAD_REQUEST, 40002, "파라미터 값 중 유효하지 않은 값이 있습니다."), API_INVALID_TYPE(HttpStatus.BAD_REQUEST, 40003, "파라미터 타입이 잘못되었습니다."), /* 60000부터 비즈니스 예외 */ + /** + * 60000 : alias error + */ + ALIAS_NOT_FOUND(HttpStatus.NOT_FOUND, 60001, "존재하지 않는 ALIAS 입니다."); + + ; private final HttpStatus httpStatus; diff --git a/src/main/java/konkuk/thip/user/adapter/in/web/UserCommandController.java b/src/main/java/konkuk/thip/user/adapter/in/web/UserCommandController.java index ef67414d3..e799f0509 100644 --- a/src/main/java/konkuk/thip/user/adapter/in/web/UserCommandController.java +++ b/src/main/java/konkuk/thip/user/adapter/in/web/UserCommandController.java @@ -1,10 +1,26 @@ package konkuk.thip.user.adapter.in.web; +import konkuk.thip.common.dto.BaseResponse; +import konkuk.thip.user.adapter.in.web.request.UserSignupRequest; +import konkuk.thip.user.adapter.in.web.response.UserSignupResponse; +import konkuk.thip.user.application.port.in.UserSignupUseCase; +import konkuk.thip.user.application.port.in.dto.UserSignupCommand; import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController @RequiredArgsConstructor public class UserCommandController { + private final UserSignupUseCase userSignupUseCase; + + @PostMapping("/users/signup") + public BaseResponse signup(@Validated @RequestBody UserSignupRequest request) { + return BaseResponse.ok(UserSignupResponse.of( + userSignupUseCase.signup(request.toCommand())) + ); + } } diff --git a/src/main/java/konkuk/thip/user/adapter/in/web/request/UserSignupRequest.java b/src/main/java/konkuk/thip/user/adapter/in/web/request/UserSignupRequest.java index 1050f1c9e..96c9725a3 100644 --- a/src/main/java/konkuk/thip/user/adapter/in/web/request/UserSignupRequest.java +++ b/src/main/java/konkuk/thip/user/adapter/in/web/request/UserSignupRequest.java @@ -1,7 +1,28 @@ package konkuk.thip.user.adapter.in.web.request; -import lombok.Getter; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import konkuk.thip.user.application.port.in.dto.UserSignupCommand; +import org.hibernate.validator.constraints.Length; -@Getter -public class UserSignupRequest { +public record UserSignupRequest( + @NotNull(message = "aliasId는 필수입니다.") + Long aliasId, + + @NotBlank(message = "닉네임은 공백일 수 없습니다.") + @Length(max = 10, message = "닉네임은 최대 10자 입니다.") + String nickname, + + @NotBlank(message = "이메일은 공백일 수 없습니다.") + @Email(message = "이메일 형식이 올바르지 않습니다.") + String email +) { + public UserSignupCommand toCommand() { + return UserSignupCommand.builder() + .aliasId(aliasId) + .nickname(nickname) + .email(email) + .build(); + } } diff --git a/src/main/java/konkuk/thip/user/adapter/in/web/response/DummyResponse.java b/src/main/java/konkuk/thip/user/adapter/in/web/response/DummyResponse.java deleted file mode 100644 index 6b9591bdf..000000000 --- a/src/main/java/konkuk/thip/user/adapter/in/web/response/DummyResponse.java +++ /dev/null @@ -1,7 +0,0 @@ -package konkuk.thip.user.adapter.in.web.response; - -import lombok.Getter; - -@Getter -public class DummyResponse { -} diff --git a/src/main/java/konkuk/thip/user/adapter/in/web/response/UserSignupResponse.java b/src/main/java/konkuk/thip/user/adapter/in/web/response/UserSignupResponse.java new file mode 100644 index 000000000..f5a490e6e --- /dev/null +++ b/src/main/java/konkuk/thip/user/adapter/in/web/response/UserSignupResponse.java @@ -0,0 +1,7 @@ +package konkuk.thip.user.adapter.in.web.response; + +public record UserSignupResponse(Long userId) { + public static UserSignupResponse of(Long userId) { + return new UserSignupResponse(userId); + } +} \ No newline at end of file diff --git a/src/main/java/konkuk/thip/user/adapter/out/jpa/AliasJpaEntity.java b/src/main/java/konkuk/thip/user/adapter/out/jpa/AliasJpaEntity.java index 45356bee4..a5e885417 100644 --- a/src/main/java/konkuk/thip/user/adapter/out/jpa/AliasJpaEntity.java +++ b/src/main/java/konkuk/thip/user/adapter/out/jpa/AliasJpaEntity.java @@ -18,7 +18,12 @@ public class AliasJpaEntity extends BaseJpaEntity { @Column(name = "alias_id") private Long aliasId; - @Column(name = "alias_value",length = 50, nullable = false) + @Column(name = "alias_value", length = 50, nullable = false) private String value; + @Column(name = "image_url", columnDefinition = "TEXT", nullable = false) + private String imageUrl; + + @Column(name = "alias_color", length = 10, nullable = false) + private String color; } diff --git a/src/main/java/konkuk/thip/user/adapter/out/jpa/UserJpaEntity.java b/src/main/java/konkuk/thip/user/adapter/out/jpa/UserJpaEntity.java index 2663aafb5..6258411ae 100644 --- a/src/main/java/konkuk/thip/user/adapter/out/jpa/UserJpaEntity.java +++ b/src/main/java/konkuk/thip/user/adapter/out/jpa/UserJpaEntity.java @@ -18,6 +18,9 @@ public class UserJpaEntity extends BaseJpaEntity { @Column(name = "user_id") private Long userId; + @Column(name = "email", length = 100, nullable = false) + private String email; + @Column(length = 60, nullable = false) private String nickname; diff --git a/src/main/java/konkuk/thip/user/adapter/out/mapper/AliasMapper.java b/src/main/java/konkuk/thip/user/adapter/out/mapper/AliasMapper.java index bf53f67f7..eac3e0f45 100644 --- a/src/main/java/konkuk/thip/user/adapter/out/mapper/AliasMapper.java +++ b/src/main/java/konkuk/thip/user/adapter/out/mapper/AliasMapper.java @@ -10,6 +10,8 @@ public class AliasMapper { public AliasJpaEntity toJpaEntity(Alias alias) { return AliasJpaEntity.builder() .value(alias.getValue()) + .imageUrl(alias.getImageUrl()) + .color(alias.getColor()) .build(); } @@ -17,6 +19,8 @@ public Alias toDomainEntity(AliasJpaEntity aliasJpaEntity) { return Alias.builder() .id(aliasJpaEntity.getAliasId()) .value(aliasJpaEntity.getValue()) + .imageUrl(aliasJpaEntity.getImageUrl()) + .color(aliasJpaEntity.getColor()) .createdAt(aliasJpaEntity.getCreatedAt()) .modifiedAt(aliasJpaEntity.getModifiedAt()) .status(aliasJpaEntity.getStatus()) diff --git a/src/main/java/konkuk/thip/user/adapter/out/mapper/UserMapper.java b/src/main/java/konkuk/thip/user/adapter/out/mapper/UserMapper.java index c91558dd4..38780e9ef 100644 --- a/src/main/java/konkuk/thip/user/adapter/out/mapper/UserMapper.java +++ b/src/main/java/konkuk/thip/user/adapter/out/mapper/UserMapper.java @@ -11,6 +11,7 @@ public class UserMapper { public UserJpaEntity toJpaEntity(User user, AliasJpaEntity aliasJpaEntity) { return UserJpaEntity.builder() + .email(user.getEmail()) .nickname(user.getNickname()) .imageUrl(user.getImageUrl()) .role(UserRole.from(user.getUserRole())) @@ -21,6 +22,7 @@ public UserJpaEntity toJpaEntity(User user, AliasJpaEntity aliasJpaEntity) { public User toDomainEntity(UserJpaEntity userJpaEntity) { return User.builder() .id(userJpaEntity.getUserId()) + .email(userJpaEntity.getEmail()) .nickname(userJpaEntity.getNickname()) .imageUrl(userJpaEntity.getImageUrl()) .userRole(userJpaEntity.getRole().getType()) diff --git a/src/main/java/konkuk/thip/user/adapter/out/persistence/AliasCommandPersistenceAdapter.java b/src/main/java/konkuk/thip/user/adapter/out/persistence/AliasCommandPersistenceAdapter.java new file mode 100644 index 000000000..154feaf72 --- /dev/null +++ b/src/main/java/konkuk/thip/user/adapter/out/persistence/AliasCommandPersistenceAdapter.java @@ -0,0 +1,27 @@ +package konkuk.thip.user.adapter.out.persistence; + +import konkuk.thip.common.exception.EntityNotFoundException; +import konkuk.thip.user.adapter.out.jpa.AliasJpaEntity; +import konkuk.thip.user.adapter.out.mapper.AliasMapper; +import konkuk.thip.user.application.port.out.AliasCommandPort; +import konkuk.thip.user.domain.Alias; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; + +import static konkuk.thip.common.exception.code.ErrorCode.ALIAS_NOT_FOUND; + +@Repository +@RequiredArgsConstructor +public class AliasCommandPersistenceAdapter implements AliasCommandPort { + + private final AliasMapper aliasMapper; + private final AliasJpaRepository aliasJpaRepository; + + @Override + public Alias findById(Long aliasId) { + AliasJpaEntity aliasJpaEntity = aliasJpaRepository.findById(aliasId).orElseThrow( + () -> new EntityNotFoundException(ALIAS_NOT_FOUND)); + + return aliasMapper.toDomainEntity(aliasJpaEntity); + } +} diff --git a/src/main/java/konkuk/thip/user/adapter/out/persistence/UserCommandPersistenceAdapter.java b/src/main/java/konkuk/thip/user/adapter/out/persistence/UserCommandPersistenceAdapter.java index f6dac4d5c..7838356c5 100644 --- a/src/main/java/konkuk/thip/user/adapter/out/persistence/UserCommandPersistenceAdapter.java +++ b/src/main/java/konkuk/thip/user/adapter/out/persistence/UserCommandPersistenceAdapter.java @@ -1,15 +1,31 @@ package konkuk.thip.user.adapter.out.persistence; +import konkuk.thip.common.exception.EntityNotFoundException; +import konkuk.thip.user.adapter.out.jpa.AliasJpaEntity; +import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; import konkuk.thip.user.adapter.out.mapper.UserMapper; import konkuk.thip.user.application.port.out.UserCommandPort; +import konkuk.thip.user.domain.User; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; +import static konkuk.thip.common.exception.code.ErrorCode.ALIAS_NOT_FOUND; + @Repository @RequiredArgsConstructor public class UserCommandPersistenceAdapter implements UserCommandPort { - private final UserJpaRepository jpaRepository; + private final UserJpaRepository userJpaRepository; + private final AliasJpaRepository aliasJpaRepository; + private final UserMapper userMapper; + @Override + public Long save(User user) { + AliasJpaEntity aliasJpaEntity = aliasJpaRepository.findById(user.getAliasId()).orElseThrow( + () -> new EntityNotFoundException(ALIAS_NOT_FOUND)); + + UserJpaEntity userJpaEntity = userMapper.toJpaEntity(user, aliasJpaEntity); + return userJpaRepository.save(userJpaEntity).getUserId(); + } } diff --git a/src/main/java/konkuk/thip/user/application/port/in/DummyUseCase.java b/src/main/java/konkuk/thip/user/application/port/in/DummyUseCase.java deleted file mode 100644 index 33abe266c..000000000 --- a/src/main/java/konkuk/thip/user/application/port/in/DummyUseCase.java +++ /dev/null @@ -1,5 +0,0 @@ -package konkuk.thip.user.application.port.in; - -public interface DummyUseCase { - -} diff --git a/src/main/java/konkuk/thip/user/application/port/in/UserSignupUseCase.java b/src/main/java/konkuk/thip/user/application/port/in/UserSignupUseCase.java new file mode 100644 index 000000000..a8024b9af --- /dev/null +++ b/src/main/java/konkuk/thip/user/application/port/in/UserSignupUseCase.java @@ -0,0 +1,8 @@ +package konkuk.thip.user.application.port.in; + +import konkuk.thip.user.application.port.in.dto.UserSignupCommand; + +public interface UserSignupUseCase { + + Long signup(UserSignupCommand command); +} diff --git a/src/main/java/konkuk/thip/user/application/port/in/dto/UserSignupCommand.java b/src/main/java/konkuk/thip/user/application/port/in/dto/UserSignupCommand.java new file mode 100644 index 000000000..38aef5a36 --- /dev/null +++ b/src/main/java/konkuk/thip/user/application/port/in/dto/UserSignupCommand.java @@ -0,0 +1,10 @@ +package konkuk.thip.user.application.port.in.dto; + +import lombok.Builder; + +@Builder +public record UserSignupCommand( + Long aliasId, + String nickname, + String email +) {} diff --git a/src/main/java/konkuk/thip/user/application/port/out/AliasCommandPort.java b/src/main/java/konkuk/thip/user/application/port/out/AliasCommandPort.java new file mode 100644 index 000000000..be3bbf093 --- /dev/null +++ b/src/main/java/konkuk/thip/user/application/port/out/AliasCommandPort.java @@ -0,0 +1,8 @@ +package konkuk.thip.user.application.port.out; + +import konkuk.thip.user.domain.Alias; + +public interface AliasCommandPort { + + Alias findById(Long aliasId); +} diff --git a/src/main/java/konkuk/thip/user/application/port/out/UserCommandPort.java b/src/main/java/konkuk/thip/user/application/port/out/UserCommandPort.java index f5af3b857..2a24705e7 100644 --- a/src/main/java/konkuk/thip/user/application/port/out/UserCommandPort.java +++ b/src/main/java/konkuk/thip/user/application/port/out/UserCommandPort.java @@ -1,6 +1,9 @@ package konkuk.thip.user.application.port.out; +import konkuk.thip.user.domain.User; public interface UserCommandPort { + Long save(User user); + } diff --git a/src/main/java/konkuk/thip/user/application/service/UserService.java b/src/main/java/konkuk/thip/user/application/service/UserService.java deleted file mode 100644 index 150990b52..000000000 --- a/src/main/java/konkuk/thip/user/application/service/UserService.java +++ /dev/null @@ -1,11 +0,0 @@ -package konkuk.thip.user.application.service; - -import konkuk.thip.user.application.port.in.DummyUseCase; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class UserService implements DummyUseCase { - -} diff --git a/src/main/java/konkuk/thip/user/application/service/UserSignupService.java b/src/main/java/konkuk/thip/user/application/service/UserSignupService.java new file mode 100644 index 000000000..b32c2028e --- /dev/null +++ b/src/main/java/konkuk/thip/user/application/service/UserSignupService.java @@ -0,0 +1,33 @@ +package konkuk.thip.user.application.service; + +import konkuk.thip.user.application.port.in.UserSignupUseCase; +import konkuk.thip.user.application.port.in.dto.UserSignupCommand; +import konkuk.thip.user.application.port.out.AliasCommandPort; +import konkuk.thip.user.application.port.out.UserCommandPort; +import konkuk.thip.user.domain.Alias; +import konkuk.thip.user.domain.User; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import static konkuk.thip.user.adapter.out.jpa.UserRole.USER; + + +@Service +@RequiredArgsConstructor +public class UserSignupService implements UserSignupUseCase { + + private final UserCommandPort userCommandPort; + private final AliasCommandPort aliasCommandPort; + + @Override + @Transactional + public Long signup(UserSignupCommand command) { + Alias alias = aliasCommandPort.findById(command.aliasId()); + User user = User.withoutId( + command.email(), command.nickname(), alias.getImageUrl(), USER.getType(), alias.getId() + ); + + return userCommandPort.save(user); + } +} diff --git a/src/main/java/konkuk/thip/user/domain/Alias.java b/src/main/java/konkuk/thip/user/domain/Alias.java index 242a4c868..76e8c599d 100644 --- a/src/main/java/konkuk/thip/user/domain/Alias.java +++ b/src/main/java/konkuk/thip/user/domain/Alias.java @@ -11,4 +11,8 @@ public class Alias extends BaseDomainEntity { private Long id; private String value; + + private String imageUrl; + + private String color; } diff --git a/src/main/java/konkuk/thip/user/domain/User.java b/src/main/java/konkuk/thip/user/domain/User.java index 889956d26..b7d1e1ebf 100644 --- a/src/main/java/konkuk/thip/user/domain/User.java +++ b/src/main/java/konkuk/thip/user/domain/User.java @@ -10,6 +10,8 @@ public class User extends BaseDomainEntity { private Long id; + private String email; + private String nickname; private String imageUrl; @@ -18,4 +20,15 @@ public class User extends BaseDomainEntity { private Long aliasId; + public static User withoutId(String email, String nickname, String imageUrl, String userRole, Long aliasId) { + return User.builder() + .id(null) + .email(email) + .nickname(nickname) + .imageUrl(imageUrl) + .userRole(userRole) + .aliasId(aliasId) + .build(); + } + } diff --git a/src/test/java/konkuk/thip/domain/feed/adapter/out/jpa/FeedJpaEntityTest.java b/src/test/java/konkuk/thip/feed/adapter/out/jpa/FeedJpaEntityTest.java similarity index 91% rename from src/test/java/konkuk/thip/domain/feed/adapter/out/jpa/FeedJpaEntityTest.java rename to src/test/java/konkuk/thip/feed/adapter/out/jpa/FeedJpaEntityTest.java index 52ec6a91e..2b1d18198 100644 --- a/src/test/java/konkuk/thip/domain/feed/adapter/out/jpa/FeedJpaEntityTest.java +++ b/src/test/java/konkuk/thip/feed/adapter/out/jpa/FeedJpaEntityTest.java @@ -1,10 +1,9 @@ -package konkuk.thip.domain.feed.adapter.out.jpa; +package konkuk.thip.feed.adapter.out.jpa; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import konkuk.thip.book.adapter.out.jpa.BookJpaEntity; import konkuk.thip.book.adapter.out.persistence.BookJpaRepository; -import konkuk.thip.feed.adapter.out.jpa.FeedJpaEntity; import konkuk.thip.feed.adapter.out.persistence.FeedJpaRepository; import konkuk.thip.user.adapter.out.jpa.AliasJpaEntity; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; @@ -39,10 +38,16 @@ class FeedJpaEntityTest { private FeedJpaRepository feedRepository; private UserJpaEntity createUser() { - AliasJpaEntity alias = AliasJpaEntity.builder().value("익명1").build(); + AliasJpaEntity alias = AliasJpaEntity.builder() + .value("칭호") + .imageUrl("test-image-url") + .color("red") + .build(); + aliasRepository.save(alias); UserJpaEntity user = UserJpaEntity.builder() + .email("test@test.com") .nickname("테스터") .imageUrl("https://test.img") .aliasForUserJpaEntity(alias) diff --git a/src/test/java/konkuk/thip/domain/room/adapter/out/jpa/RecordJpaEntityTest.java b/src/test/java/konkuk/thip/room/adapter/out/jpa/RecordJpaEntityTest.java similarity index 89% rename from src/test/java/konkuk/thip/domain/room/adapter/out/jpa/RecordJpaEntityTest.java rename to src/test/java/konkuk/thip/room/adapter/out/jpa/RecordJpaEntityTest.java index aeca4ea6d..a69653bfe 100644 --- a/src/test/java/konkuk/thip/domain/room/adapter/out/jpa/RecordJpaEntityTest.java +++ b/src/test/java/konkuk/thip/room/adapter/out/jpa/RecordJpaEntityTest.java @@ -1,12 +1,10 @@ -package konkuk.thip.domain.room.adapter.out.jpa; +package konkuk.thip.room.adapter.out.jpa; import jakarta.persistence.EntityManager; import konkuk.thip.book.adapter.out.jpa.BookJpaEntity; import konkuk.thip.book.adapter.out.persistence.BookJpaRepository; import konkuk.thip.record.adapter.out.jpa.RecordJpaEntity; import konkuk.thip.record.adapter.out.persistence.RecordJpaRepository; -import konkuk.thip.room.adapter.out.jpa.CategoryJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; import konkuk.thip.room.adapter.out.persistence.CategoryJpaRepository; import konkuk.thip.room.adapter.out.persistence.RoomJpaRepository; import konkuk.thip.user.adapter.out.jpa.AliasJpaEntity; @@ -50,10 +48,16 @@ class RecordJpaEntityTest { private CategoryJpaRepository categoryRepository; private UserJpaEntity createUser() { - AliasJpaEntity alias = AliasJpaEntity.builder().value("익명1").build(); + AliasJpaEntity alias = AliasJpaEntity.builder() + .value("칭호") + .imageUrl("test-image-url") + .color("red") + .build(); + aliasRepository.save(alias); UserJpaEntity user = UserJpaEntity.builder() + .email("test@test.com") .nickname("테스터") .imageUrl("https://test.img") .aliasForUserJpaEntity(alias) @@ -89,7 +93,12 @@ private RoomJpaEntity createRoom(BookJpaEntity book, CategoryJpaEntity category) } private CategoryJpaEntity createCategory() { - AliasJpaEntity alias = AliasJpaEntity.builder().value("익명1").build(); + AliasJpaEntity alias = AliasJpaEntity.builder() + .value("칭호") + .imageUrl("test-image-url") + .color("red") + .build(); + aliasRepository.save(alias); return categoryRepository.save(CategoryJpaEntity.builder() diff --git a/src/test/java/konkuk/thip/domain/room/adapter/out/jpa/RoomJpaEntityTest.java b/src/test/java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntityTest.java similarity index 94% rename from src/test/java/konkuk/thip/domain/room/adapter/out/jpa/RoomJpaEntityTest.java rename to src/test/java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntityTest.java index 54d9b3157..302a5d683 100644 --- a/src/test/java/konkuk/thip/domain/room/adapter/out/jpa/RoomJpaEntityTest.java +++ b/src/test/java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntityTest.java @@ -1,12 +1,10 @@ -package konkuk.thip.domain.room.adapter.out.jpa; +package konkuk.thip.room.adapter.out.jpa; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import konkuk.thip.book.adapter.out.jpa.BookJpaEntity; -import konkuk.thip.room.adapter.out.jpa.CategoryJpaEntity; import konkuk.thip.book.adapter.out.persistence.BookJpaRepository; import konkuk.thip.room.adapter.out.persistence.CategoryJpaRepository; -import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; import konkuk.thip.room.adapter.out.persistence.RoomJpaRepository; import konkuk.thip.user.adapter.out.jpa.AliasJpaEntity; import konkuk.thip.user.adapter.out.persistence.AliasJpaRepository; @@ -54,7 +52,9 @@ void saveAndFindRoom() { bookRepository.save(book); AliasJpaEntity alias = AliasJpaEntity.builder() - .value("칭호1") + .value("칭호") + .imageUrl("test-image-url") + .color("red") .build(); aliasRepository.save(alias); diff --git a/src/test/java/konkuk/thip/domain/room/adapter/out/jpa/VoteJpaEntityTest.java b/src/test/java/konkuk/thip/room/adapter/out/jpa/VoteJpaEntityTest.java similarity index 89% rename from src/test/java/konkuk/thip/domain/room/adapter/out/jpa/VoteJpaEntityTest.java rename to src/test/java/konkuk/thip/room/adapter/out/jpa/VoteJpaEntityTest.java index a00b4b5ea..8c626f0e3 100644 --- a/src/test/java/konkuk/thip/domain/room/adapter/out/jpa/VoteJpaEntityTest.java +++ b/src/test/java/konkuk/thip/room/adapter/out/jpa/VoteJpaEntityTest.java @@ -1,11 +1,9 @@ -package konkuk.thip.domain.room.adapter.out.jpa; +package konkuk.thip.room.adapter.out.jpa; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import konkuk.thip.book.adapter.out.jpa.BookJpaEntity; import konkuk.thip.book.adapter.out.persistence.BookJpaRepository; -import konkuk.thip.room.adapter.out.jpa.CategoryJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; import konkuk.thip.room.adapter.out.persistence.CategoryJpaRepository; import konkuk.thip.room.adapter.out.persistence.RoomJpaRepository; import konkuk.thip.user.adapter.out.jpa.AliasJpaEntity; @@ -51,10 +49,15 @@ class VoteJpaEntityTest { private CategoryJpaRepository categoryRepository; private UserJpaEntity createUser() { - AliasJpaEntity alias = AliasJpaEntity.builder().value("익명1").build(); + AliasJpaEntity alias = AliasJpaEntity.builder() + .value("칭호") + .imageUrl("test-image-url") + .color("red") + .build(); aliasRepository.save(alias); UserJpaEntity user = UserJpaEntity.builder() + .email("test@test.com") .nickname("테스터") .imageUrl("https://test.img") .aliasForUserJpaEntity(alias) @@ -90,7 +93,12 @@ private RoomJpaEntity createRoom(BookJpaEntity book, CategoryJpaEntity category) } private CategoryJpaEntity createCategory() { - AliasJpaEntity alias = AliasJpaEntity.builder().value("익명1").build(); + AliasJpaEntity alias = AliasJpaEntity.builder() + .value("칭호") + .imageUrl("test-image-url") + .color("red") + .build(); + aliasRepository.save(alias); return categoryRepository.save(CategoryJpaEntity.builder() diff --git a/src/test/java/konkuk/thip/user/adapter/in/web/UserCommandControllerTest.java b/src/test/java/konkuk/thip/user/adapter/in/web/UserCommandControllerTest.java new file mode 100644 index 000000000..fe6ef27c2 --- /dev/null +++ b/src/test/java/konkuk/thip/user/adapter/in/web/UserCommandControllerTest.java @@ -0,0 +1,175 @@ +package konkuk.thip.user.adapter.in.web; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import konkuk.thip.user.adapter.in.web.request.UserSignupRequest; +import konkuk.thip.user.adapter.out.jpa.AliasJpaEntity; +import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; +import konkuk.thip.user.adapter.out.persistence.AliasJpaRepository; +import konkuk.thip.user.adapter.out.persistence.UserJpaRepository; +import org.junit.jupiter.api.DisplayName; +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.http.MediaType; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; + +import static konkuk.thip.common.exception.code.ErrorCode.API_INVALID_PARAM; +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@ActiveProfiles("test") +@AutoConfigureMockMvc +class UserCommandControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private AliasJpaRepository aliasJpaRepository; + + @Autowired + private UserJpaRepository userJpaRepository; + + @Test + @DisplayName("[칭호id, 닉네임, 이메일] 정보를 바탕으로 회원가입을 진행한다.") + void signup_success() throws Exception { + //given : alias 생성, 회원가입 request 생성 + AliasJpaEntity aliasJpaEntity = AliasJpaEntity.builder() + .value("칭호") + .color("blue") + .imageUrl("http://image.url") + .build(); + aliasJpaRepository.save(aliasJpaEntity); + + UserSignupRequest request = new UserSignupRequest( + aliasJpaEntity.getAliasId(), + "테스트 유저", + "test@test.com" + ); + + //when : 회원가입 api 호출 + ResultActions result = mockMvc.perform(post("/users/signup") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))); + + //then + result.andExpect(status().isOk()) + .andExpect(jsonPath("$.data.userId").exists()); + + String json = result.andReturn().getResponse().getContentAsString(); + JsonNode jsonNode = objectMapper.readTree(json); + Long userId = jsonNode.path("data").path("userId").asLong(); + + UserJpaEntity userJpaEntity = userJpaRepository.findById(userId).orElse(null); + + assertThat(userJpaEntity.getAliasForUserJpaEntity().getAliasId()).isEqualTo(request.aliasId()); + assertThat(userJpaEntity.getNickname()).isEqualTo(request.nickname()); + assertThat(userJpaEntity.getEmail()).isEqualTo(request.email()); + } + + @Test + @DisplayName("[칭호id]값이 null일 경우, 400 error가 발생한다.") + void signup_whenAliasIdNull_thenBadRequest() throws Exception { + //given: aliasId null + UserSignupRequest request = new UserSignupRequest( + null, + "테스트유저", + "test@test.com" + ); + + //when //then + mockMvc.perform(post("/users/signup") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.code").value(API_INVALID_PARAM.getCode())) + .andExpect(jsonPath("$.message", containsString("aliasId는 필수입니다."))); + } + + @Test + @DisplayName("[닉네임]값이 공백일 경우, 400 error가 발생한다.") + void signup_whenNicknameBlank_thenBadRequest() throws Exception { + //given: nickname blank + UserSignupRequest request = new UserSignupRequest( + 1L, + "", + "test@test.com" + ); + + //when //then + mockMvc.perform(post("/users/signup") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.code").value(API_INVALID_PARAM.getCode())) + .andExpect(jsonPath("$.message", containsString("닉네임은 공백일 수 없습니다."))); + } + + @Test + @DisplayName("[닉네임]값이 11자 이상일 경우, 400 error가 발생한다.") + void signup_whenNicknameTooLong_thenBadRequest() throws Exception { + //given: nickname blank + UserSignupRequest request = new UserSignupRequest( + 1L, + "11자_닉네임_입니다", + "test@test.com" + ); + + //when //then + mockMvc.perform(post("/users/signup") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.code").value(API_INVALID_PARAM.getCode())) + .andExpect(jsonPath("$.message", containsString("닉네임은 최대 10자 입니다."))); + } + + @Test + @DisplayName("[이메일]값이 공백일 경우, 400 error가 발생한다.") + void signup_whenEmailBlank_thenBadRequest() throws Exception { + //given + UserSignupRequest request = new UserSignupRequest( + 1L, + "테스트유저", + "" + ); + + //when //then + mockMvc.perform(post("/users/signup") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.code").value(API_INVALID_PARAM.getCode())) + .andExpect(jsonPath("$.message", containsString("이메일은 공백일 수 없습니다."))); + } + + @Test + @DisplayName("[이메일]값이 유효한 이메일 형식이 아닐 경우, 400 error가 발생한다.") + void signup_whenEmailInvalidFormat_thenBadRequest() throws Exception { + //given + UserSignupRequest request = new UserSignupRequest( + 1L, + "테스트유저", + "invalid-email-format" + ); + + //when //then + mockMvc.perform(post("/users/signup") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.code").value("40002")) + .andExpect(jsonPath("$.message", containsString("이메일 형식이 올바르지 않습니다."))); + } +} diff --git a/src/test/java/konkuk/thip/domain/user/adapter/out/jpa/UserJpaEntityTest.java b/src/test/java/konkuk/thip/user/adapter/out/jpa/UserJpaEntityTest.java similarity index 81% rename from src/test/java/konkuk/thip/domain/user/adapter/out/jpa/UserJpaEntityTest.java rename to src/test/java/konkuk/thip/user/adapter/out/jpa/UserJpaEntityTest.java index c6263a504..afbe8ab44 100644 --- a/src/test/java/konkuk/thip/domain/user/adapter/out/jpa/UserJpaEntityTest.java +++ b/src/test/java/konkuk/thip/user/adapter/out/jpa/UserJpaEntityTest.java @@ -1,10 +1,7 @@ -package konkuk.thip.domain.user.adapter.out.jpa; +package konkuk.thip.user.adapter.out.jpa; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; -import konkuk.thip.user.adapter.out.jpa.AliasJpaEntity; -import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; -import konkuk.thip.user.adapter.out.jpa.UserRole; import konkuk.thip.user.adapter.out.persistence.AliasJpaRepository; import konkuk.thip.user.adapter.out.persistence.UserJpaRepository; import org.junit.jupiter.api.DisplayName; @@ -34,14 +31,17 @@ void saveAndFindUser() { // given AliasJpaEntity alias = AliasJpaEntity.builder() .value("칭호") + .imageUrl("test-image-url") + .color("red") .build(); aliasJpaRepository.save(alias); UserJpaEntity user = UserJpaEntity.builder() - .nickname("테스트유저") - .imageUrl("http://image.url") - .role(UserRole.USER) + .email("test@test.com") + .nickname("테스터") + .imageUrl("https://test.img") .aliasForUserJpaEntity(alias) + .role(UserRole.USER) .build(); // when @@ -52,7 +52,7 @@ void saveAndFindUser() { UserJpaEntity foundUser = userRepository.findById(user.getUserId()).orElseThrow(); // then - assertThat(foundUser.getNickname()).isEqualTo("테스트유저"); + assertThat(foundUser.getNickname()).isEqualTo("테스터"); assertThat(foundUser.getAliasForUserJpaEntity().getValue()).isEqualTo("칭호"); assertThat(foundUser.getRole()).isEqualTo(UserRole.USER); }