test: 실습 2부 내용 반영
This commit is contained in:
@@ -1,10 +1,10 @@
|
|||||||
package com.example.demo.controller;
|
package com.example.demo.common.controller;
|
||||||
|
|
||||||
import static org.springframework.http.HttpStatus.FORBIDDEN;
|
import static org.springframework.http.HttpStatus.FORBIDDEN;
|
||||||
import static org.springframework.http.HttpStatus.NOT_FOUND;
|
import static org.springframework.http.HttpStatus.NOT_FOUND;
|
||||||
|
|
||||||
import com.example.demo.exception.CertificationCodeNotMatchedException;
|
import com.example.demo.common.domain.exception.CertificationCodeNotMatchedException;
|
||||||
import com.example.demo.exception.ResourceNotFoundException;
|
import com.example.demo.common.domain.exception.ResourceNotFoundException;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.example.demo.controller;
|
package com.example.demo.common.controller;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.example.demo.exception;
|
package com.example.demo.common.domain.exception;
|
||||||
|
|
||||||
public class CertificationCodeNotMatchedException extends RuntimeException {
|
public class CertificationCodeNotMatchedException extends RuntimeException {
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.example.demo.exception;
|
package com.example.demo.common.domain.exception;
|
||||||
|
|
||||||
public class ResourceNotFoundException extends RuntimeException {
|
public class ResourceNotFoundException extends RuntimeException {
|
||||||
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.example.demo.common.infrastructure;
|
||||||
|
|
||||||
|
import com.example.demo.common.service.port.ClockHolder;
|
||||||
|
import java.time.Clock;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class SystemClockHolder implements ClockHolder {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long millis() {
|
||||||
|
return Clock.systemUTC().millis();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.example.demo.common.infrastructure;
|
||||||
|
|
||||||
|
import com.example.demo.common.service.port.UuidHolder;
|
||||||
|
import java.util.UUID;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class SystemUuidHolder implements UuidHolder {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String random() {
|
||||||
|
return UUID.randomUUID().toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.example.demo.common.service.port;
|
||||||
|
|
||||||
|
public interface ClockHolder {
|
||||||
|
|
||||||
|
long millis();
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.example.demo.common.service.port;
|
||||||
|
|
||||||
|
public interface UuidHolder {
|
||||||
|
|
||||||
|
String random();
|
||||||
|
}
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
package com.example.demo.controller;
|
|
||||||
|
|
||||||
import com.example.demo.model.dto.PostResponse;
|
|
||||||
import com.example.demo.model.dto.PostUpdateDto;
|
|
||||||
import com.example.demo.repository.PostEntity;
|
|
||||||
import com.example.demo.service.PostService;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
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.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
@Tag(name = "게시물(posts)")
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/posts")
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class PostController {
|
|
||||||
|
|
||||||
private final PostService postService;
|
|
||||||
private final UserController userController;
|
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
|
||||||
public ResponseEntity<PostResponse> getPostById(@PathVariable long id) {
|
|
||||||
return ResponseEntity
|
|
||||||
.ok()
|
|
||||||
.body(toResponse(postService.getById(id)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@PutMapping("/{id}")
|
|
||||||
public ResponseEntity<PostResponse> updatePost(@PathVariable long id, @RequestBody PostUpdateDto postUpdateDto) {
|
|
||||||
return ResponseEntity
|
|
||||||
.ok()
|
|
||||||
.body(toResponse(postService.update(id, postUpdateDto)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public PostResponse toResponse(PostEntity postEntity) {
|
|
||||||
PostResponse PostResponse = new PostResponse();
|
|
||||||
PostResponse.setId(postEntity.getId());
|
|
||||||
PostResponse.setContent(postEntity.getContent());
|
|
||||||
PostResponse.setCreatedAt(postEntity.getCreatedAt());
|
|
||||||
PostResponse.setModifiedAt(postEntity.getModifiedAt());
|
|
||||||
PostResponse.setWriter(userController.toResponse(postEntity.getWriter()));
|
|
||||||
return PostResponse;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
package com.example.demo.controller;
|
|
||||||
|
|
||||||
import com.example.demo.model.dto.MyProfileResponse;
|
|
||||||
import com.example.demo.model.dto.UserResponse;
|
|
||||||
import com.example.demo.model.dto.UserUpdateDto;
|
|
||||||
import com.example.demo.repository.UserEntity;
|
|
||||||
import com.example.demo.service.UserService;
|
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
|
||||||
import io.swagger.v3.oas.annotations.enums.ParameterIn;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import java.net.URI;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
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.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RequestHeader;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
@Tag(name = "유저(users)")
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/users")
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class UserController {
|
|
||||||
|
|
||||||
private final UserService userService;
|
|
||||||
|
|
||||||
@ResponseStatus
|
|
||||||
@GetMapping("/{id}")
|
|
||||||
public ResponseEntity<UserResponse> getUserById(@PathVariable long id) {
|
|
||||||
return ResponseEntity
|
|
||||||
.ok()
|
|
||||||
.body(toResponse(userService.getById(id)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/{id}/verify")
|
|
||||||
public ResponseEntity<Void> verifyEmail(
|
|
||||||
@PathVariable long id,
|
|
||||||
@RequestParam String certificationCode) {
|
|
||||||
userService.verifyEmail(id, certificationCode);
|
|
||||||
return ResponseEntity.status(HttpStatus.FOUND)
|
|
||||||
.location(URI.create("http://localhost:3000"))
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/me")
|
|
||||||
public ResponseEntity<MyProfileResponse> getMyInfo(
|
|
||||||
@Parameter(name = "EMAIL", in = ParameterIn.HEADER)
|
|
||||||
@RequestHeader("EMAIL") String email // 일반적으로 스프링 시큐리티를 사용한다면 UserPrincipal 에서 가져옵니다.
|
|
||||||
) {
|
|
||||||
UserEntity userEntity = userService.getByEmail(email);
|
|
||||||
userService.login(userEntity.getId());
|
|
||||||
return ResponseEntity
|
|
||||||
.ok()
|
|
||||||
.body(toMyProfileResponse(userEntity));
|
|
||||||
}
|
|
||||||
|
|
||||||
@PutMapping("/me")
|
|
||||||
@Parameter(in = ParameterIn.HEADER, name = "EMAIL")
|
|
||||||
public ResponseEntity<MyProfileResponse> updateMyInfo(
|
|
||||||
@Parameter(name = "EMAIL", in = ParameterIn.HEADER)
|
|
||||||
@RequestHeader("EMAIL") String email, // 일반적으로 스프링 시큐리티를 사용한다면 UserPrincipal 에서 가져옵니다.
|
|
||||||
@RequestBody UserUpdateDto userUpdateDto
|
|
||||||
) {
|
|
||||||
UserEntity userEntity = userService.getByEmail(email);
|
|
||||||
userEntity = userService.update(userEntity.getId(), userUpdateDto);
|
|
||||||
return ResponseEntity
|
|
||||||
.ok()
|
|
||||||
.body(toMyProfileResponse(userEntity));
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserResponse toResponse(UserEntity userEntity) {
|
|
||||||
UserResponse userResponse = new UserResponse();
|
|
||||||
userResponse.setId(userEntity.getId());
|
|
||||||
userResponse.setEmail(userEntity.getEmail());
|
|
||||||
userResponse.setNickname(userEntity.getNickname());
|
|
||||||
userResponse.setStatus(userEntity.getStatus());
|
|
||||||
userResponse.setLastLoginAt(userEntity.getLastLoginAt());
|
|
||||||
return userResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MyProfileResponse toMyProfileResponse(UserEntity userEntity) {
|
|
||||||
MyProfileResponse myProfileResponse = new MyProfileResponse();
|
|
||||||
myProfileResponse.setId(userEntity.getId());
|
|
||||||
myProfileResponse.setEmail(userEntity.getEmail());
|
|
||||||
myProfileResponse.setNickname(userEntity.getNickname());
|
|
||||||
myProfileResponse.setStatus(userEntity.getStatus());
|
|
||||||
myProfileResponse.setAddress(userEntity.getAddress());
|
|
||||||
myProfileResponse.setLastLoginAt(userEntity.getLastLoginAt());
|
|
||||||
return myProfileResponse;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package com.example.demo.model.dto;
|
|
||||||
|
|
||||||
import com.example.demo.model.UserStatus;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public class MyProfileResponse {
|
|
||||||
|
|
||||||
private Long id;
|
|
||||||
private String email;
|
|
||||||
private String nickname;
|
|
||||||
private String address;
|
|
||||||
private UserStatus status;
|
|
||||||
private Long lastLoginAt;
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package com.example.demo.model.dto;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public class PostResponse {
|
|
||||||
|
|
||||||
private Long id;
|
|
||||||
private String content;
|
|
||||||
private Long createdAt;
|
|
||||||
private Long modifiedAt;
|
|
||||||
private UserResponse writer;
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package com.example.demo.model.dto;
|
|
||||||
|
|
||||||
import com.example.demo.model.UserStatus;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public class UserResponse {
|
|
||||||
|
|
||||||
private Long id;
|
|
||||||
private String email;
|
|
||||||
private String nickname;
|
|
||||||
private UserStatus status;
|
|
||||||
private Long lastLoginAt;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.example.demo.post.controller;
|
||||||
|
|
||||||
|
import com.example.demo.post.controller.port.PostService;
|
||||||
|
import com.example.demo.post.controller.response.PostResponse;
|
||||||
|
import com.example.demo.post.domain.PostUpdate;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
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.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@Tag(name = "게시물(posts)")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/posts")
|
||||||
|
@Builder
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class PostController {
|
||||||
|
|
||||||
|
private final PostService postService;
|
||||||
|
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public ResponseEntity<PostResponse> getById(@PathVariable long id) {
|
||||||
|
return ResponseEntity
|
||||||
|
.ok()
|
||||||
|
.body(PostResponse.from(postService.getById(id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{id}")
|
||||||
|
public ResponseEntity<PostResponse> update(@PathVariable long id, @RequestBody PostUpdate postUpdate) {
|
||||||
|
return ResponseEntity
|
||||||
|
.ok()
|
||||||
|
.body(PostResponse.from(postService.update(id, postUpdate)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
package com.example.demo.controller;
|
package com.example.demo.post.controller;
|
||||||
|
|
||||||
import com.example.demo.model.dto.PostCreateDto;
|
import com.example.demo.post.controller.port.PostService;
|
||||||
import com.example.demo.model.dto.PostResponse;
|
import com.example.demo.post.controller.response.PostResponse;
|
||||||
import com.example.demo.service.PostService;
|
import com.example.demo.post.domain.PostCreate;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.Builder;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
@@ -15,16 +16,16 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
@Tag(name = "게시물(posts)")
|
@Tag(name = "게시물(posts)")
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/posts")
|
@RequestMapping("/api/posts")
|
||||||
|
@Builder
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class PostCreateController {
|
public class PostCreateController {
|
||||||
|
|
||||||
private final PostService postService;
|
private final PostService postService;
|
||||||
private final PostController postController;
|
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public ResponseEntity<PostResponse> createPost(@RequestBody PostCreateDto postCreateDto) {
|
public ResponseEntity<PostResponse> create(@RequestBody PostCreate postCreate) {
|
||||||
return ResponseEntity
|
return ResponseEntity
|
||||||
.status(HttpStatus.CREATED)
|
.status(HttpStatus.CREATED)
|
||||||
.body(postController.toResponse(postService.create(postCreateDto)));
|
.body(PostResponse.from(postService.create(postCreate)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.example.demo.post.controller.port;
|
||||||
|
|
||||||
|
import com.example.demo.post.domain.Post;
|
||||||
|
import com.example.demo.post.domain.PostCreate;
|
||||||
|
import com.example.demo.post.domain.PostUpdate;
|
||||||
|
|
||||||
|
public interface PostService {
|
||||||
|
|
||||||
|
Post getById(long id);
|
||||||
|
|
||||||
|
Post create(PostCreate postCreate);
|
||||||
|
|
||||||
|
Post update(long id, PostUpdate postUpdate);
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.example.demo.post.controller.response;
|
||||||
|
|
||||||
|
import com.example.demo.post.domain.Post;
|
||||||
|
import com.example.demo.user.controller.response.UserResponse;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Builder
|
||||||
|
public class PostResponse {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
private String content;
|
||||||
|
private Long createdAt;
|
||||||
|
private Long modifiedAt;
|
||||||
|
private UserResponse writer;
|
||||||
|
|
||||||
|
public static PostResponse from(Post post) {
|
||||||
|
return PostResponse.builder()
|
||||||
|
.id(post.getId())
|
||||||
|
.content(post.getContent())
|
||||||
|
.createdAt(post.getCreatedAt())
|
||||||
|
.modifiedAt(post.getModifiedAt())
|
||||||
|
.writer(UserResponse.from(post.getWriter()))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
42
src/main/java/com/example/demo/post/domain/Post.java
Normal file
42
src/main/java/com/example/demo/post/domain/Post.java
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package com.example.demo.post.domain;
|
||||||
|
|
||||||
|
import com.example.demo.common.service.port.ClockHolder;
|
||||||
|
import com.example.demo.user.domain.User;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class Post {
|
||||||
|
private final Long id;
|
||||||
|
private final String content;
|
||||||
|
private final Long createdAt;
|
||||||
|
private final Long modifiedAt;
|
||||||
|
private final User writer;
|
||||||
|
|
||||||
|
@Builder
|
||||||
|
public Post(Long id, String content, Long createdAt, Long modifiedAt, User writer) {
|
||||||
|
this.id = id;
|
||||||
|
this.content = content;
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
this.modifiedAt = modifiedAt;
|
||||||
|
this.writer = writer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Post from(User writer, PostCreate postCreate, ClockHolder clockHolder) {
|
||||||
|
return Post.builder()
|
||||||
|
.content(postCreate.getContent())
|
||||||
|
.writer(writer)
|
||||||
|
.createdAt(clockHolder.millis())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Post update(PostUpdate postUpdate, ClockHolder clockHolder) {
|
||||||
|
return Post.builder()
|
||||||
|
.id(id)
|
||||||
|
.content(postUpdate.getContent())
|
||||||
|
.createdAt(createdAt)
|
||||||
|
.modifiedAt(clockHolder.millis())
|
||||||
|
.writer(writer)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
package com.example.demo.model.dto;
|
package com.example.demo.post.domain;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class PostCreateDto {
|
public class PostCreate {
|
||||||
|
|
||||||
private final long writerId;
|
private final long writerId;
|
||||||
private final String content;
|
private final String content;
|
||||||
|
|
||||||
@Builder
|
@Builder
|
||||||
public PostCreateDto(
|
public PostCreate(
|
||||||
@JsonProperty("writerId") long writerId,
|
@JsonProperty("writerId") long writerId,
|
||||||
@JsonProperty("content") String content) {
|
@JsonProperty("content") String content) {
|
||||||
this.writerId = writerId;
|
this.writerId = writerId;
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
package com.example.demo.model.dto;
|
package com.example.demo.post.domain;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class PostUpdateDto {
|
public class PostUpdate {
|
||||||
|
|
||||||
private final String content;
|
private final String content;
|
||||||
|
|
||||||
@Builder
|
@Builder
|
||||||
public PostUpdateDto(
|
public PostUpdate(
|
||||||
@JsonProperty("content") String content) {
|
@JsonProperty("content") String content) {
|
||||||
this.content = content;
|
this.content = content;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package com.example.demo.post.infrastructure;
|
||||||
|
|
||||||
|
import com.example.demo.post.domain.Post;
|
||||||
|
import com.example.demo.user.infrastructure.UserEntity;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.JoinColumn;
|
||||||
|
import jakarta.persistence.ManyToOne;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Entity
|
||||||
|
@Table(name = "posts")
|
||||||
|
public class PostEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(name = "content")
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
@Column(name = "created_at")
|
||||||
|
private Long createdAt;
|
||||||
|
|
||||||
|
@Column(name = "modified_at")
|
||||||
|
private Long modifiedAt;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "user_id")
|
||||||
|
private UserEntity writer;
|
||||||
|
|
||||||
|
public static PostEntity from(Post post) {
|
||||||
|
PostEntity postEntity = new PostEntity();
|
||||||
|
postEntity.id = post.getId();
|
||||||
|
postEntity.content = post.getContent();
|
||||||
|
postEntity.createdAt = post.getCreatedAt();
|
||||||
|
postEntity.modifiedAt = post.getModifiedAt();
|
||||||
|
postEntity.writer = UserEntity.from(post.getWriter());
|
||||||
|
return postEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Post toModel() {
|
||||||
|
return Post.builder()
|
||||||
|
.id(id)
|
||||||
|
.content(content)
|
||||||
|
.createdAt(createdAt)
|
||||||
|
.modifiedAt(modifiedAt)
|
||||||
|
.writer(writer.toModel())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.example.demo.post.infrastructure;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface PostJpaRepository extends JpaRepository<PostEntity, Long> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.example.demo.post.infrastructure;
|
||||||
|
|
||||||
|
import com.example.demo.post.domain.Post;
|
||||||
|
import com.example.demo.post.service.port.PostRepository;
|
||||||
|
import java.util.Optional;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class PostRepositoryImpl implements PostRepository {
|
||||||
|
|
||||||
|
private final PostJpaRepository postJpaRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Post> findById(long id) {
|
||||||
|
return postJpaRepository.findById(id).map(PostEntity::toModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Post save(Post post) {
|
||||||
|
return postJpaRepository.save(PostEntity.from(post)).toModel();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.example.demo.post.service;
|
||||||
|
|
||||||
|
import com.example.demo.common.domain.exception.ResourceNotFoundException;
|
||||||
|
import com.example.demo.common.service.port.ClockHolder;
|
||||||
|
import com.example.demo.post.controller.port.PostService;
|
||||||
|
import com.example.demo.post.domain.Post;
|
||||||
|
import com.example.demo.post.domain.PostCreate;
|
||||||
|
import com.example.demo.post.domain.PostUpdate;
|
||||||
|
import com.example.demo.post.service.port.PostRepository;
|
||||||
|
import com.example.demo.user.domain.User;
|
||||||
|
import com.example.demo.user.service.port.UserRepository;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Builder
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class PostServiceImpl implements PostService {
|
||||||
|
|
||||||
|
private final PostRepository postRepository;
|
||||||
|
private final UserRepository userRepository;
|
||||||
|
private final ClockHolder clockHolder;
|
||||||
|
|
||||||
|
public Post getById(long id) {
|
||||||
|
return postRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("Posts", id));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Post create(PostCreate postCreate) {
|
||||||
|
User writer = userRepository.getById(postCreate.getWriterId());
|
||||||
|
Post post = Post.from(writer, postCreate, clockHolder);
|
||||||
|
return postRepository.save(post);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Post update(long id, PostUpdate postUpdate) {
|
||||||
|
Post post = getById(id);
|
||||||
|
post = post.update(postUpdate, clockHolder);
|
||||||
|
return postRepository.save(post);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.example.demo.post.service.port;
|
||||||
|
|
||||||
|
import com.example.demo.post.domain.Post;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public interface PostRepository {
|
||||||
|
|
||||||
|
Optional<Post> findById(long id);
|
||||||
|
|
||||||
|
Post save(Post post);
|
||||||
|
}
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
package com.example.demo.repository;
|
|
||||||
|
|
||||||
import jakarta.persistence.Column;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
|
||||||
import jakarta.persistence.GenerationType;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
import jakarta.persistence.JoinColumn;
|
|
||||||
import jakarta.persistence.ManyToOne;
|
|
||||||
import jakarta.persistence.Table;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@Entity
|
|
||||||
@Table(name = "posts")
|
|
||||||
public class PostEntity {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@Column(name = "content")
|
|
||||||
private String content;
|
|
||||||
|
|
||||||
@Column(name = "created_at")
|
|
||||||
private Long createdAt;
|
|
||||||
|
|
||||||
@Column(name = "modified_at")
|
|
||||||
private Long modifiedAt;
|
|
||||||
|
|
||||||
@ManyToOne
|
|
||||||
@JoinColumn(name = "user_id")
|
|
||||||
private UserEntity writer;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
package com.example.demo.repository;
|
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
|
|
||||||
public interface PostRepository extends JpaRepository<PostEntity, Long> {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
package com.example.demo.repository;
|
|
||||||
|
|
||||||
import com.example.demo.model.UserStatus;
|
|
||||||
import jakarta.persistence.Column;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.EnumType;
|
|
||||||
import jakarta.persistence.Enumerated;
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
|
||||||
import jakarta.persistence.GenerationType;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
import jakarta.persistence.Table;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@Entity
|
|
||||||
@Table(name = "users")
|
|
||||||
public class UserEntity {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@Column(name = "email")
|
|
||||||
private String email;
|
|
||||||
|
|
||||||
@Column(name = "nickname")
|
|
||||||
private String nickname;
|
|
||||||
|
|
||||||
@Column(name = "address")
|
|
||||||
private String address;
|
|
||||||
|
|
||||||
@Column(name = "certification_code")
|
|
||||||
private String certificationCode;
|
|
||||||
|
|
||||||
@Column(name = "status")
|
|
||||||
@Enumerated(EnumType.STRING)
|
|
||||||
private UserStatus status;
|
|
||||||
|
|
||||||
@Column(name = "last_login_at")
|
|
||||||
private Long lastLoginAt;
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
package com.example.demo.service;
|
|
||||||
|
|
||||||
import com.example.demo.exception.ResourceNotFoundException;
|
|
||||||
import com.example.demo.model.dto.PostCreateDto;
|
|
||||||
import com.example.demo.model.dto.PostUpdateDto;
|
|
||||||
import com.example.demo.repository.PostEntity;
|
|
||||||
import com.example.demo.repository.PostRepository;
|
|
||||||
import com.example.demo.repository.UserEntity;
|
|
||||||
import java.time.Clock;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class PostService {
|
|
||||||
|
|
||||||
private final PostRepository postRepository;
|
|
||||||
private final UserService userService;
|
|
||||||
|
|
||||||
public PostEntity getById(long id) {
|
|
||||||
return postRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("Posts", id));
|
|
||||||
}
|
|
||||||
|
|
||||||
public PostEntity create(PostCreateDto postCreateDto) {
|
|
||||||
UserEntity userEntity = userService.getById(postCreateDto.getWriterId());
|
|
||||||
PostEntity postEntity = new PostEntity();
|
|
||||||
postEntity.setWriter(userEntity);
|
|
||||||
postEntity.setContent(postCreateDto.getContent());
|
|
||||||
postEntity.setCreatedAt(Clock.systemUTC().millis());
|
|
||||||
return postRepository.save(postEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PostEntity update(long id, PostUpdateDto postUpdateDto) {
|
|
||||||
PostEntity postEntity = getById(id);
|
|
||||||
postEntity.setContent(postUpdateDto.getContent());
|
|
||||||
postEntity.setModifiedAt(Clock.systemUTC().millis());
|
|
||||||
return postRepository.save(postEntity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
package com.example.demo.service;
|
|
||||||
|
|
||||||
import com.example.demo.exception.CertificationCodeNotMatchedException;
|
|
||||||
import com.example.demo.exception.ResourceNotFoundException;
|
|
||||||
import com.example.demo.model.UserStatus;
|
|
||||||
import com.example.demo.model.dto.UserCreateDto;
|
|
||||||
import com.example.demo.model.dto.UserUpdateDto;
|
|
||||||
import com.example.demo.repository.UserEntity;
|
|
||||||
import com.example.demo.repository.UserRepository;
|
|
||||||
import java.time.Clock;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.mail.SimpleMailMessage;
|
|
||||||
import org.springframework.mail.javamail.JavaMailSender;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class UserService {
|
|
||||||
|
|
||||||
private final UserRepository userRepository;
|
|
||||||
private final JavaMailSender mailSender;
|
|
||||||
|
|
||||||
public UserEntity getByEmail(String email) {
|
|
||||||
return userRepository.findByEmailAndStatus(email, UserStatus.ACTIVE)
|
|
||||||
.orElseThrow(() -> new ResourceNotFoundException("Users", email));
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserEntity getById(long id) {
|
|
||||||
return userRepository.findByIdAndStatus(id, UserStatus.ACTIVE)
|
|
||||||
.orElseThrow(() -> new ResourceNotFoundException("Users", id));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public UserEntity create(UserCreateDto userCreateDto) {
|
|
||||||
UserEntity userEntity = new UserEntity();
|
|
||||||
userEntity.setEmail(userCreateDto.getEmail());
|
|
||||||
userEntity.setNickname(userCreateDto.getNickname());
|
|
||||||
userEntity.setAddress(userCreateDto.getAddress());
|
|
||||||
userEntity.setStatus(UserStatus.PENDING);
|
|
||||||
userEntity.setCertificationCode(UUID.randomUUID().toString());
|
|
||||||
userEntity = userRepository.save(userEntity);
|
|
||||||
String certificationUrl = generateCertificationUrl(userEntity);
|
|
||||||
sendCertificationEmail(userCreateDto.getEmail(), certificationUrl);
|
|
||||||
return userEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public UserEntity update(long id, UserUpdateDto userUpdateDto) {
|
|
||||||
UserEntity userEntity = getById(id);
|
|
||||||
userEntity.setNickname(userUpdateDto.getNickname());
|
|
||||||
userEntity.setAddress(userUpdateDto.getAddress());
|
|
||||||
userEntity = userRepository.save(userEntity);
|
|
||||||
return userEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public void login(long id) {
|
|
||||||
UserEntity userEntity = userRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("Users", id));
|
|
||||||
userEntity.setLastLoginAt(Clock.systemUTC().millis());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public void verifyEmail(long id, String certificationCode) {
|
|
||||||
UserEntity userEntity = userRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("Users", id));
|
|
||||||
if (!certificationCode.equals(userEntity.getCertificationCode())) {
|
|
||||||
throw new CertificationCodeNotMatchedException();
|
|
||||||
}
|
|
||||||
userEntity.setStatus(UserStatus.ACTIVE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendCertificationEmail(String email, String certificationUrl) {
|
|
||||||
SimpleMailMessage message = new SimpleMailMessage();
|
|
||||||
message.setTo(email);
|
|
||||||
message.setSubject("Please certify your email address");
|
|
||||||
message.setText("Please click the following link to certify your email address: " + certificationUrl);
|
|
||||||
mailSender.send(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String generateCertificationUrl(UserEntity userEntity) {
|
|
||||||
return "http://localhost:8080/api/users/" + userEntity.getId() + "/verify?certificationCode=" + userEntity.getCertificationCode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package com.example.demo.user.controller;
|
||||||
|
|
||||||
|
import com.example.demo.user.controller.port.UserService;
|
||||||
|
import com.example.demo.user.controller.response.MyProfileResponse;
|
||||||
|
import com.example.demo.user.domain.User;
|
||||||
|
import com.example.demo.user.domain.UserUpdate;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.enums.ParameterIn;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestHeader;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@Tag(name = "유저(users)")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/users")
|
||||||
|
@Builder
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class MyInfoController {
|
||||||
|
|
||||||
|
private final UserService userService;
|
||||||
|
|
||||||
|
@GetMapping("/me")
|
||||||
|
public ResponseEntity<MyProfileResponse> get(
|
||||||
|
@Parameter(name = "EMAIL", in = ParameterIn.HEADER)
|
||||||
|
@RequestHeader("EMAIL") String email // 일반적으로 스프링 시큐리티를 사용한다면 UserPrincipal 에서 가져옵니다.
|
||||||
|
) {
|
||||||
|
User user = userService.getByEmail(email);
|
||||||
|
userService.login(user.getId());
|
||||||
|
user = userService.getByEmail(email);
|
||||||
|
return ResponseEntity
|
||||||
|
.ok()
|
||||||
|
.body(MyProfileResponse.from(user));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/me")
|
||||||
|
@Parameter(in = ParameterIn.HEADER, name = "EMAIL")
|
||||||
|
public ResponseEntity<MyProfileResponse> update(
|
||||||
|
@Parameter(name = "EMAIL", in = ParameterIn.HEADER)
|
||||||
|
@RequestHeader("EMAIL") String email, // 일반적으로 스프링 시큐리티를 사용한다면 UserPrincipal 에서 가져옵니다.
|
||||||
|
@RequestBody UserUpdate userUpdate
|
||||||
|
) {
|
||||||
|
User user = userService.getByEmail(email);
|
||||||
|
user = userService.update(user.getId(), userUpdate);
|
||||||
|
return ResponseEntity
|
||||||
|
.ok()
|
||||||
|
.body(MyProfileResponse.from(user));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package com.example.demo.user.controller;
|
||||||
|
|
||||||
|
import com.example.demo.user.controller.port.UserService;
|
||||||
|
import com.example.demo.user.controller.response.UserResponse;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import java.net.URI;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@Tag(name = "유저(users)")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/users")
|
||||||
|
@Builder
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class UserController {
|
||||||
|
|
||||||
|
private final UserService userService;
|
||||||
|
|
||||||
|
@ResponseStatus
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public ResponseEntity<UserResponse> getById(@PathVariable long id) {
|
||||||
|
return ResponseEntity
|
||||||
|
.ok()
|
||||||
|
.body(UserResponse.from(userService.getById(id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{id}/verify")
|
||||||
|
public ResponseEntity<Void> verifyEmail(
|
||||||
|
@PathVariable long id,
|
||||||
|
@RequestParam String certificationCode) {
|
||||||
|
userService.verifyEmail(id, certificationCode);
|
||||||
|
return ResponseEntity.status(HttpStatus.FOUND)
|
||||||
|
.location(URI.create("http://localhost:3000"))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
package com.example.demo.controller;
|
package com.example.demo.user.controller;
|
||||||
|
|
||||||
import com.example.demo.model.dto.UserCreateDto;
|
import com.example.demo.user.controller.port.UserService;
|
||||||
import com.example.demo.model.dto.UserResponse;
|
import com.example.demo.user.controller.response.UserResponse;
|
||||||
import com.example.demo.repository.UserEntity;
|
import com.example.demo.user.domain.User;
|
||||||
import com.example.demo.service.UserService;
|
import com.example.demo.user.domain.UserCreate;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.Builder;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
@@ -16,18 +17,18 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
@Tag(name = "유저(users)")
|
@Tag(name = "유저(users)")
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/users")
|
@RequestMapping("/api/users")
|
||||||
|
@Builder
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class UserCreateController {
|
public class UserCreateController {
|
||||||
|
|
||||||
private final UserController userController;
|
|
||||||
private final UserService userService;
|
private final UserService userService;
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public ResponseEntity<UserResponse> createUser(@RequestBody UserCreateDto userCreateDto) {
|
public ResponseEntity<UserResponse> create(@RequestBody UserCreate userCreate) {
|
||||||
UserEntity userEntity = userService.create(userCreateDto);
|
User user = userService.create(userCreate);
|
||||||
return ResponseEntity
|
return ResponseEntity
|
||||||
.status(HttpStatus.CREATED)
|
.status(HttpStatus.CREATED)
|
||||||
.body(userController.toResponse(userEntity));
|
.body(UserResponse.from(user));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.example.demo.user.controller.port;
|
||||||
|
|
||||||
|
import com.example.demo.user.domain.User;
|
||||||
|
import com.example.demo.user.domain.UserCreate;
|
||||||
|
import com.example.demo.user.domain.UserUpdate;
|
||||||
|
|
||||||
|
public interface UserService {
|
||||||
|
|
||||||
|
User getByEmail(String email);
|
||||||
|
|
||||||
|
User getById(long id);
|
||||||
|
|
||||||
|
User create(UserCreate userCreate);
|
||||||
|
|
||||||
|
User update(long id, UserUpdate userUpdate);
|
||||||
|
|
||||||
|
void login(long id);
|
||||||
|
|
||||||
|
void verifyEmail(long id, String certificationCode);
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.example.demo.user.controller.response;
|
||||||
|
|
||||||
|
import com.example.demo.user.domain.User;
|
||||||
|
import com.example.demo.user.domain.UserStatus;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Builder
|
||||||
|
public class MyProfileResponse {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
private String email;
|
||||||
|
private String nickname;
|
||||||
|
private String address;
|
||||||
|
private UserStatus status;
|
||||||
|
private Long lastLoginAt;
|
||||||
|
|
||||||
|
public static MyProfileResponse from(User user) {
|
||||||
|
return MyProfileResponse.builder()
|
||||||
|
.id(user.getId())
|
||||||
|
.email(user.getEmail())
|
||||||
|
.nickname(user.getNickname())
|
||||||
|
.address(user.getAddress())
|
||||||
|
.status(user.getStatus())
|
||||||
|
.lastLoginAt(user.getLastLoginAt())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.example.demo.user.controller.response;
|
||||||
|
|
||||||
|
import com.example.demo.user.domain.User;
|
||||||
|
import com.example.demo.user.domain.UserStatus;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Builder
|
||||||
|
public class UserResponse {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
private String email;
|
||||||
|
private String nickname;
|
||||||
|
private UserStatus status;
|
||||||
|
private Long lastLoginAt;
|
||||||
|
|
||||||
|
public static UserResponse from(User user) {
|
||||||
|
return UserResponse.builder()
|
||||||
|
.id(user.getId())
|
||||||
|
.email(user.getEmail())
|
||||||
|
.nickname(user.getNickname())
|
||||||
|
.status(user.getStatus())
|
||||||
|
.lastLoginAt(user.getLastLoginAt())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
81
src/main/java/com/example/demo/user/domain/User.java
Normal file
81
src/main/java/com/example/demo/user/domain/User.java
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
package com.example.demo.user.domain;
|
||||||
|
|
||||||
|
import com.example.demo.common.domain.exception.CertificationCodeNotMatchedException;
|
||||||
|
import com.example.demo.common.service.port.ClockHolder;
|
||||||
|
import com.example.demo.common.service.port.UuidHolder;
|
||||||
|
import java.time.Clock;
|
||||||
|
import java.util.UUID;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class User {
|
||||||
|
|
||||||
|
private final Long id;
|
||||||
|
private final String email;
|
||||||
|
private final String nickname;
|
||||||
|
private final String address;
|
||||||
|
private final String certificationCode;
|
||||||
|
private final UserStatus status;
|
||||||
|
private final Long lastLoginAt;
|
||||||
|
|
||||||
|
@Builder
|
||||||
|
public User(Long id, String email, String nickname, String address, String certificationCode, UserStatus status, Long lastLoginAt) {
|
||||||
|
this.id = id;
|
||||||
|
this.email = email;
|
||||||
|
this.nickname = nickname;
|
||||||
|
this.address = address;
|
||||||
|
this.certificationCode = certificationCode;
|
||||||
|
this.status = status;
|
||||||
|
this.lastLoginAt = lastLoginAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static User from(UserCreate userCreate, UuidHolder uuidHolder) {
|
||||||
|
return User.builder()
|
||||||
|
.email(userCreate.getEmail())
|
||||||
|
.nickname(userCreate.getNickname())
|
||||||
|
.address(userCreate.getAddress())
|
||||||
|
.status(UserStatus.PENDING)
|
||||||
|
.certificationCode(uuidHolder.random())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public User update(UserUpdate userUpdate) {
|
||||||
|
return User.builder()
|
||||||
|
.id(id)
|
||||||
|
.email(email)
|
||||||
|
.nickname(userUpdate.getNickname())
|
||||||
|
.address(userUpdate.getAddress())
|
||||||
|
.certificationCode(certificationCode)
|
||||||
|
.status(status)
|
||||||
|
.lastLoginAt(lastLoginAt)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public User login(ClockHolder clockHolder) {
|
||||||
|
return User.builder()
|
||||||
|
.id(id)
|
||||||
|
.email(email)
|
||||||
|
.nickname(nickname)
|
||||||
|
.address(address)
|
||||||
|
.certificationCode(certificationCode)
|
||||||
|
.status(status)
|
||||||
|
.lastLoginAt(clockHolder.millis())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public User certificate(String certificationCode) {
|
||||||
|
if (!this.certificationCode.equals(certificationCode)) {
|
||||||
|
throw new CertificationCodeNotMatchedException();
|
||||||
|
}
|
||||||
|
return User.builder()
|
||||||
|
.id(id)
|
||||||
|
.email(email)
|
||||||
|
.nickname(nickname)
|
||||||
|
.address(address)
|
||||||
|
.certificationCode(certificationCode)
|
||||||
|
.status(UserStatus.ACTIVE)
|
||||||
|
.lastLoginAt(lastLoginAt)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
package com.example.demo.model.dto;
|
package com.example.demo.user.domain;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class UserCreateDto {
|
public class UserCreate {
|
||||||
|
|
||||||
private final String email;
|
private final String email;
|
||||||
private final String nickname;
|
private final String nickname;
|
||||||
private final String address;
|
private final String address;
|
||||||
|
|
||||||
@Builder
|
@Builder
|
||||||
public UserCreateDto(
|
public UserCreate(
|
||||||
@JsonProperty("email") String email,
|
@JsonProperty("email") String email,
|
||||||
@JsonProperty("nickname") String nickname,
|
@JsonProperty("nickname") String nickname,
|
||||||
@JsonProperty("address") String address) {
|
@JsonProperty("address") String address) {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.example.demo.model;
|
package com.example.demo.user.domain;
|
||||||
|
|
||||||
public enum UserStatus {
|
public enum UserStatus {
|
||||||
PENDING, INACTIVE, ACTIVE
|
PENDING, INACTIVE, ACTIVE
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
package com.example.demo.model.dto;
|
package com.example.demo.user.domain;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class UserUpdateDto {
|
public class UserUpdate {
|
||||||
|
|
||||||
private final String nickname;
|
private final String nickname;
|
||||||
private final String address;
|
private final String address;
|
||||||
|
|
||||||
@Builder
|
@Builder
|
||||||
public UserUpdateDto(
|
public UserUpdate(
|
||||||
@JsonProperty("nickname") String nickname,
|
@JsonProperty("nickname") String nickname,
|
||||||
@JsonProperty("address") String address) {
|
@JsonProperty("address") String address) {
|
||||||
this.nickname = nickname;
|
this.nickname = nickname;
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.example.demo.user.infrastructure;
|
||||||
|
|
||||||
|
import com.example.demo.user.service.port.MailSender;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.mail.SimpleMailMessage;
|
||||||
|
import org.springframework.mail.javamail.JavaMailSender;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class MailSenderImpl implements MailSender {
|
||||||
|
|
||||||
|
private final JavaMailSender javaMailSender;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void send(String email, String title, String content) {
|
||||||
|
SimpleMailMessage message = new SimpleMailMessage();
|
||||||
|
message.setTo(email);
|
||||||
|
message.setSubject(title);
|
||||||
|
message.setText(content);
|
||||||
|
javaMailSender.send(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
package com.example.demo.user.infrastructure;
|
||||||
|
|
||||||
|
import com.example.demo.user.domain.User;
|
||||||
|
import com.example.demo.user.domain.UserStatus;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.EnumType;
|
||||||
|
import jakarta.persistence.Enumerated;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Entity
|
||||||
|
@Table(name = "users")
|
||||||
|
public class UserEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(name = "email")
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
@Column(name = "nickname")
|
||||||
|
private String nickname;
|
||||||
|
|
||||||
|
@Column(name = "address")
|
||||||
|
private String address;
|
||||||
|
|
||||||
|
@Column(name = "certification_code")
|
||||||
|
private String certificationCode;
|
||||||
|
|
||||||
|
@Column(name = "status")
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private UserStatus status;
|
||||||
|
|
||||||
|
@Column(name = "last_login_at")
|
||||||
|
private Long lastLoginAt;
|
||||||
|
|
||||||
|
public static UserEntity from(User user) {
|
||||||
|
UserEntity userEntity = new UserEntity();
|
||||||
|
userEntity.id = user.getId();
|
||||||
|
userEntity.email = user.getEmail();
|
||||||
|
userEntity.nickname = user.getNickname();
|
||||||
|
userEntity.address = user.getAddress();
|
||||||
|
userEntity.certificationCode = user.getCertificationCode();
|
||||||
|
userEntity.status = user.getStatus();
|
||||||
|
userEntity.lastLoginAt = user.getLastLoginAt();
|
||||||
|
return userEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User toModel() {
|
||||||
|
return User.builder()
|
||||||
|
.id(id)
|
||||||
|
.email(email)
|
||||||
|
.nickname(nickname)
|
||||||
|
.address(address)
|
||||||
|
.certificationCode(certificationCode)
|
||||||
|
.status(status)
|
||||||
|
.lastLoginAt(lastLoginAt)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
package com.example.demo.repository;
|
package com.example.demo.user.infrastructure;
|
||||||
|
|
||||||
import com.example.demo.model.UserStatus;
|
import com.example.demo.user.domain.UserStatus;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
public interface UserRepository extends JpaRepository<UserEntity, Long> {
|
public interface UserJpaRepository extends JpaRepository<UserEntity, Long> {
|
||||||
|
|
||||||
Optional<UserEntity> findByIdAndStatus(long id, UserStatus userStatus);
|
Optional<UserEntity> findByIdAndStatus(long id, UserStatus userStatus);
|
||||||
|
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package com.example.demo.user.infrastructure;
|
||||||
|
|
||||||
|
import com.example.demo.common.domain.exception.ResourceNotFoundException;
|
||||||
|
import com.example.demo.user.domain.User;
|
||||||
|
import com.example.demo.user.domain.UserStatus;
|
||||||
|
import com.example.demo.user.service.port.UserRepository;
|
||||||
|
import java.util.Optional;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class UserRepositoryImpl implements UserRepository {
|
||||||
|
|
||||||
|
private final UserJpaRepository userJpaRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User getById(long id) {
|
||||||
|
return findById(id).orElseThrow(() -> new ResourceNotFoundException("Users", id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<User> findById(long id) {
|
||||||
|
return userJpaRepository.findById(id).map(UserEntity::toModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<User> findByIdAndStatus(long id, UserStatus userStatus) {
|
||||||
|
return userJpaRepository.findByIdAndStatus(id, userStatus).map(UserEntity::toModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<User> findByEmailAndStatus(String email, UserStatus userStatus) {
|
||||||
|
return userJpaRepository.findByEmailAndStatus(email, userStatus).map(UserEntity::toModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User save(User user) {
|
||||||
|
return userJpaRepository.save(UserEntity.from(user)).toModel();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.example.demo.user.service;
|
||||||
|
|
||||||
|
import com.example.demo.user.service.port.MailSender;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CertificationService {
|
||||||
|
|
||||||
|
private final MailSender mailSender;
|
||||||
|
|
||||||
|
public void send(String email, long userId, String certificationCode) {
|
||||||
|
String certificationUrl = generateCertificationUrl(userId, certificationCode);
|
||||||
|
String title = "Please certify your email address";
|
||||||
|
String content = "Please click the following link to certify your email address: " + certificationUrl;
|
||||||
|
mailSender.send(email, title, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String generateCertificationUrl(long userId, String certificationCode) {
|
||||||
|
return "http://localhost:8080/api/users/" + userId + "/verify?certificationCode=" + certificationCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package com.example.demo.user.service;
|
||||||
|
|
||||||
|
import com.example.demo.common.domain.exception.ResourceNotFoundException;
|
||||||
|
import com.example.demo.common.service.port.ClockHolder;
|
||||||
|
import com.example.demo.common.service.port.UuidHolder;
|
||||||
|
import com.example.demo.user.controller.port.UserService;
|
||||||
|
import com.example.demo.user.domain.User;
|
||||||
|
import com.example.demo.user.domain.UserCreate;
|
||||||
|
import com.example.demo.user.domain.UserStatus;
|
||||||
|
import com.example.demo.user.domain.UserUpdate;
|
||||||
|
import com.example.demo.user.service.port.UserRepository;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Builder
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class UserServiceImpl implements UserService {
|
||||||
|
|
||||||
|
private final UserRepository userRepository;
|
||||||
|
private final CertificationService certificationService;
|
||||||
|
private final UuidHolder uuidHolder;
|
||||||
|
private final ClockHolder clockHolder;
|
||||||
|
|
||||||
|
public User getByEmail(String email) {
|
||||||
|
return userRepository.findByEmailAndStatus(email, UserStatus.ACTIVE)
|
||||||
|
.orElseThrow(() -> new ResourceNotFoundException("Users", email));
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getById(long id) {
|
||||||
|
return userRepository.findByIdAndStatus(id, UserStatus.ACTIVE)
|
||||||
|
.orElseThrow(() -> new ResourceNotFoundException("Users", id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public User create(UserCreate userCreate) {
|
||||||
|
User user = User.from(userCreate, uuidHolder);
|
||||||
|
user = userRepository.save(user);
|
||||||
|
certificationService.send(userCreate.getEmail(), user.getId(), user.getCertificationCode());
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public User update(long id, UserUpdate userUpdate) {
|
||||||
|
User user = getById(id);
|
||||||
|
user = user.update(userUpdate);
|
||||||
|
user = userRepository.save(user);
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void login(long id) {
|
||||||
|
User user = userRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("Users", id));
|
||||||
|
user = user.login(clockHolder);
|
||||||
|
userRepository.save(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void verifyEmail(long id, String certificationCode) {
|
||||||
|
User user = userRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("Users", id));
|
||||||
|
user = user.certificate(certificationCode);
|
||||||
|
userRepository.save(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.example.demo.user.service.port;
|
||||||
|
|
||||||
|
public interface MailSender {
|
||||||
|
|
||||||
|
void send(String email, String title, String content);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.example.demo.user.service.port;
|
||||||
|
|
||||||
|
import com.example.demo.user.domain.User;
|
||||||
|
import com.example.demo.user.domain.UserStatus;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public interface UserRepository {
|
||||||
|
|
||||||
|
User getById(long id);
|
||||||
|
|
||||||
|
Optional<User> findById(long id);
|
||||||
|
|
||||||
|
Optional<User> findByIdAndStatus(long id, UserStatus userStatus);
|
||||||
|
|
||||||
|
Optional<User> findByEmailAndStatus(String email, UserStatus userStatus);
|
||||||
|
|
||||||
|
User save(User user);
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.example.demo.controller;
|
package com.example.demo.medium;
|
||||||
|
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.example.demo.controller;
|
package com.example.demo.medium;
|
||||||
|
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
||||||
@@ -6,7 +6,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
|||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
import com.example.demo.model.dto.PostUpdateDto;
|
import com.example.demo.post.domain.PostUpdate;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -59,7 +59,7 @@ public class PostControllerTest {
|
|||||||
@Test
|
@Test
|
||||||
void 사용자는_게시물을_수정할_수_있다() throws Exception {
|
void 사용자는_게시물을_수정할_수_있다() throws Exception {
|
||||||
// given
|
// given
|
||||||
PostUpdateDto postUpdateDto = PostUpdateDto.builder()
|
PostUpdate postUpdate = PostUpdate.builder()
|
||||||
.content("foobar")
|
.content("foobar")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ public class PostControllerTest {
|
|||||||
mockMvc.perform(
|
mockMvc.perform(
|
||||||
put("/api/posts/1")
|
put("/api/posts/1")
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
.content(objectMapper.writeValueAsString(postUpdateDto)))
|
.content(objectMapper.writeValueAsString(postUpdate)))
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$.id").isNumber())
|
.andExpect(jsonPath("$.id").isNumber())
|
||||||
.andExpect(jsonPath("$.content").value("foobar"))
|
.andExpect(jsonPath("$.content").value("foobar"))
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
package com.example.demo.controller;
|
package com.example.demo.medium;
|
||||||
|
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
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.jsonPath;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
import com.example.demo.model.dto.PostCreateDto;
|
import com.example.demo.post.domain.PostCreate;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -33,7 +33,7 @@ public class PostCreateControllerTest {
|
|||||||
@Test
|
@Test
|
||||||
void 사용자는_게시물을_작성할_수_있다() throws Exception {
|
void 사용자는_게시물을_작성할_수_있다() throws Exception {
|
||||||
// given
|
// given
|
||||||
PostCreateDto postCreateDto = PostCreateDto.builder()
|
PostCreate postCreate = PostCreate.builder()
|
||||||
.writerId(1)
|
.writerId(1)
|
||||||
.content("helloworld")
|
.content("helloworld")
|
||||||
.build();
|
.build();
|
||||||
@@ -43,7 +43,7 @@ public class PostCreateControllerTest {
|
|||||||
mockMvc.perform(
|
mockMvc.perform(
|
||||||
post("/api/posts")
|
post("/api/posts")
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
.content(objectMapper.writeValueAsString(postCreateDto)))
|
.content(objectMapper.writeValueAsString(postCreate)))
|
||||||
.andExpect(status().isCreated())
|
.andExpect(status().isCreated())
|
||||||
.andExpect(jsonPath("$.id").isNumber())
|
.andExpect(jsonPath("$.id").isNumber())
|
||||||
.andExpect(jsonPath("$.content").value("helloworld"))
|
.andExpect(jsonPath("$.content").value("helloworld"))
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
package com.example.demo.service;
|
package com.example.demo.medium;
|
||||||
|
|
||||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
|
|
||||||
import com.example.demo.model.dto.PostCreateDto;
|
import com.example.demo.post.domain.Post;
|
||||||
import com.example.demo.model.dto.PostUpdateDto;
|
import com.example.demo.post.domain.PostCreate;
|
||||||
import com.example.demo.repository.PostEntity;
|
import com.example.demo.post.domain.PostUpdate;
|
||||||
|
import com.example.demo.post.service.PostServiceImpl;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
@@ -22,13 +23,13 @@ import org.springframework.test.context.jdbc.SqlGroup;
|
|||||||
public class PostServiceTest {
|
public class PostServiceTest {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private PostService postService;
|
private PostServiceImpl postService;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getById는_존재하는_게시물을_내려준다() {
|
void getById는_존재하는_게시물을_내려준다() {
|
||||||
// given
|
// given
|
||||||
// when
|
// when
|
||||||
PostEntity result = postService.getById(1);
|
Post result = postService.getById(1);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result.getContent()).isEqualTo("helloworld");
|
assertThat(result.getContent()).isEqualTo("helloworld");
|
||||||
@@ -38,13 +39,13 @@ public class PostServiceTest {
|
|||||||
@Test
|
@Test
|
||||||
void postCreateDto_를_이용하여_게시물을_생성할_수_있다() {
|
void postCreateDto_를_이용하여_게시물을_생성할_수_있다() {
|
||||||
// given
|
// given
|
||||||
PostCreateDto postCreateDto = PostCreateDto.builder()
|
PostCreate postCreate = PostCreate.builder()
|
||||||
.writerId(1)
|
.writerId(1)
|
||||||
.content("foobar")
|
.content("foobar")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
PostEntity result = postService.create(postCreateDto);
|
Post result = postService.create(postCreate);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result.getId()).isNotNull();
|
assertThat(result.getId()).isNotNull();
|
||||||
@@ -55,17 +56,17 @@ public class PostServiceTest {
|
|||||||
@Test
|
@Test
|
||||||
void postUpdateDto_를_이용하여_게시물을_수정할_수_있다() {
|
void postUpdateDto_를_이용하여_게시물을_수정할_수_있다() {
|
||||||
// given
|
// given
|
||||||
PostUpdateDto postUpdateDto = PostUpdateDto.builder()
|
PostUpdate postUpdate = PostUpdate.builder()
|
||||||
.content("hello world :)")
|
.content("hello world :)")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
postService.update(1, postUpdateDto);
|
postService.update(1, postUpdate);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
PostEntity postEntity= postService.getById(1);
|
Post post = postService.getById(1);
|
||||||
assertThat(postEntity.getContent()).isEqualTo("hello world :)");
|
assertThat(post.getContent()).isEqualTo("hello world :)");
|
||||||
assertThat(postEntity.getModifiedAt()).isGreaterThan(0);
|
assertThat(post.getModifiedAt()).isGreaterThan(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.example.demo.controller;
|
package com.example.demo.medium;
|
||||||
|
|
||||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
@@ -7,10 +7,10 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
|||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
import com.example.demo.model.UserStatus;
|
import com.example.demo.user.domain.UserStatus;
|
||||||
import com.example.demo.model.dto.UserUpdateDto;
|
import com.example.demo.user.domain.UserUpdate;
|
||||||
import com.example.demo.repository.UserEntity;
|
import com.example.demo.user.infrastructure.UserEntity;
|
||||||
import com.example.demo.repository.UserRepository;
|
import com.example.demo.user.infrastructure.UserJpaRepository;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -35,7 +35,7 @@ public class UserControllerTest {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private MockMvc mockMvc;
|
private MockMvc mockMvc;
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserRepository userRepository;
|
private UserJpaRepository userJpaRepository;
|
||||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -71,7 +71,7 @@ public class UserControllerTest {
|
|||||||
get("/api/users/2/verify")
|
get("/api/users/2/verify")
|
||||||
.queryParam("certificationCode", "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab"))
|
.queryParam("certificationCode", "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab"))
|
||||||
.andExpect(status().isFound());
|
.andExpect(status().isFound());
|
||||||
UserEntity userEntity = userRepository.findById(1L).get();
|
UserEntity userEntity = userJpaRepository.findById(1L).get();
|
||||||
assertThat(userEntity.getStatus()).isEqualTo(UserStatus.ACTIVE);
|
assertThat(userEntity.getStatus()).isEqualTo(UserStatus.ACTIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ public class UserControllerTest {
|
|||||||
@Test
|
@Test
|
||||||
void 사용자는_내_정보를_수정할_수_있다() throws Exception {
|
void 사용자는_내_정보를_수정할_수_있다() throws Exception {
|
||||||
// given
|
// given
|
||||||
UserUpdateDto userUpdateDto = UserUpdateDto.builder()
|
UserUpdate userUpdate = UserUpdate.builder()
|
||||||
.nickname("kok202-n")
|
.nickname("kok202-n")
|
||||||
.address("Pangyo")
|
.address("Pangyo")
|
||||||
.build();
|
.build();
|
||||||
@@ -116,7 +116,7 @@ public class UserControllerTest {
|
|||||||
put("/api/users/me")
|
put("/api/users/me")
|
||||||
.header("EMAIL", "kok202@naver.com")
|
.header("EMAIL", "kok202@naver.com")
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
.content(objectMapper.writeValueAsString(userUpdateDto)))
|
.content(objectMapper.writeValueAsString(userUpdate)))
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$.id").value(1))
|
.andExpect(jsonPath("$.id").value(1))
|
||||||
.andExpect(jsonPath("$.email").value("kok202@naver.com"))
|
.andExpect(jsonPath("$.email").value("kok202@naver.com"))
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
package com.example.demo.controller;
|
package com.example.demo.medium;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
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.jsonPath;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
import com.example.demo.model.dto.UserCreateDto;
|
import com.example.demo.user.domain.UserCreate;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.BDDMockito;
|
import org.mockito.BDDMockito;
|
||||||
@@ -39,7 +39,7 @@ public class UserCreateControllerTest {
|
|||||||
@Test
|
@Test
|
||||||
void 사용자는_회원_가입을_할_수있고_회원가입된_사용자는_PENDING_상태이다() throws Exception {
|
void 사용자는_회원_가입을_할_수있고_회원가입된_사용자는_PENDING_상태이다() throws Exception {
|
||||||
// given
|
// given
|
||||||
UserCreateDto userCreateDto = UserCreateDto.builder()
|
UserCreate userCreate = UserCreate.builder()
|
||||||
.email("kok202@kakao.com")
|
.email("kok202@kakao.com")
|
||||||
.nickname("kok202")
|
.nickname("kok202")
|
||||||
.address("Pangyo")
|
.address("Pangyo")
|
||||||
@@ -51,7 +51,7 @@ public class UserCreateControllerTest {
|
|||||||
mockMvc.perform(
|
mockMvc.perform(
|
||||||
post("/api/users")
|
post("/api/users")
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
.content(objectMapper.writeValueAsString(userCreateDto)))
|
.content(objectMapper.writeValueAsString(userCreate)))
|
||||||
.andExpect(status().isCreated())
|
.andExpect(status().isCreated())
|
||||||
.andExpect(jsonPath("$.id").isNumber())
|
.andExpect(jsonPath("$.id").isNumber())
|
||||||
.andExpect(jsonPath("$.email").value("kok202@kakao.com"))
|
.andExpect(jsonPath("$.email").value("kok202@kakao.com"))
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
package com.example.demo.repository;
|
package com.example.demo.medium;
|
||||||
|
|
||||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
|
|
||||||
import com.example.demo.model.UserStatus;
|
import com.example.demo.user.domain.UserStatus;
|
||||||
|
import com.example.demo.user.infrastructure.UserEntity;
|
||||||
|
import com.example.demo.user.infrastructure.UserJpaRepository;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -16,16 +18,16 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
|
|||||||
@DataJpaTest(showSql = true)
|
@DataJpaTest(showSql = true)
|
||||||
@TestPropertySource("classpath:test-application.properties")
|
@TestPropertySource("classpath:test-application.properties")
|
||||||
@Sql("/sql/user-repository-test-data.sql")
|
@Sql("/sql/user-repository-test-data.sql")
|
||||||
public class UserRepositoryTest {
|
public class UserJpaRepositoryTest {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserRepository userRepository;
|
private UserJpaRepository userJpaRepository;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void findByIdAndStatus_로_유저_데이터를_찾아올_수_있다() {
|
void findByIdAndStatus_로_유저_데이터를_찾아올_수_있다() {
|
||||||
// given
|
// given
|
||||||
// when
|
// when
|
||||||
Optional<UserEntity> result = userRepository.findByIdAndStatus(1, UserStatus.ACTIVE);
|
Optional<UserEntity> result = userJpaRepository.findByIdAndStatus(1, UserStatus.ACTIVE);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result.isPresent()).isTrue();
|
assertThat(result.isPresent()).isTrue();
|
||||||
@@ -35,7 +37,7 @@ public class UserRepositoryTest {
|
|||||||
void findByIdAndStatus_는_데이터가_없으면_Optional_empty_를_내려준다() {
|
void findByIdAndStatus_는_데이터가_없으면_Optional_empty_를_내려준다() {
|
||||||
// given
|
// given
|
||||||
// when
|
// when
|
||||||
Optional<UserEntity> result = userRepository.findByIdAndStatus(1, UserStatus.PENDING);
|
Optional<UserEntity> result = userJpaRepository.findByIdAndStatus(1, UserStatus.PENDING);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result.isEmpty()).isTrue();
|
assertThat(result.isEmpty()).isTrue();
|
||||||
@@ -45,7 +47,7 @@ public class UserRepositoryTest {
|
|||||||
void findByEmailAndStatus_로_유저_데이터를_찾아올_수_있다() {
|
void findByEmailAndStatus_로_유저_데이터를_찾아올_수_있다() {
|
||||||
// given
|
// given
|
||||||
// when
|
// when
|
||||||
Optional<UserEntity> result = userRepository.findByEmailAndStatus("kok202@naver.com", UserStatus.ACTIVE);
|
Optional<UserEntity> result = userJpaRepository.findByEmailAndStatus("kok202@naver.com", UserStatus.ACTIVE);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result.isPresent()).isTrue();
|
assertThat(result.isPresent()).isTrue();
|
||||||
@@ -55,7 +57,7 @@ public class UserRepositoryTest {
|
|||||||
void findByEmailAndStatus_는_데이터가_없으면_Optional_empty_를_내려준다() {
|
void findByEmailAndStatus_는_데이터가_없으면_Optional_empty_를_내려준다() {
|
||||||
// given
|
// given
|
||||||
// when
|
// when
|
||||||
Optional<UserEntity> result = userRepository.findByEmailAndStatus("kok202@naver.com", UserStatus.PENDING);
|
Optional<UserEntity> result = userJpaRepository.findByEmailAndStatus("kok202@naver.com", UserStatus.PENDING);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result.isEmpty()).isTrue();
|
assertThat(result.isEmpty()).isTrue();
|
||||||
@@ -1,15 +1,16 @@
|
|||||||
package com.example.demo.service;
|
package com.example.demo.medium;
|
||||||
|
|
||||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
|
||||||
import com.example.demo.exception.CertificationCodeNotMatchedException;
|
import com.example.demo.common.domain.exception.CertificationCodeNotMatchedException;
|
||||||
import com.example.demo.exception.ResourceNotFoundException;
|
import com.example.demo.common.domain.exception.ResourceNotFoundException;
|
||||||
import com.example.demo.model.UserStatus;
|
import com.example.demo.user.domain.User;
|
||||||
import com.example.demo.model.dto.UserCreateDto;
|
import com.example.demo.user.domain.UserCreate;
|
||||||
import com.example.demo.model.dto.UserUpdateDto;
|
import com.example.demo.user.domain.UserStatus;
|
||||||
import com.example.demo.repository.UserEntity;
|
import com.example.demo.user.domain.UserUpdate;
|
||||||
|
import com.example.demo.user.service.UserServiceImpl;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.BDDMockito;
|
import org.mockito.BDDMockito;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -31,7 +32,7 @@ import org.springframework.test.context.jdbc.SqlGroup;
|
|||||||
public class UserServiceTest {
|
public class UserServiceTest {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserService userService;
|
private UserServiceImpl userService;
|
||||||
@MockBean
|
@MockBean
|
||||||
private JavaMailSender mailSender;
|
private JavaMailSender mailSender;
|
||||||
|
|
||||||
@@ -41,7 +42,7 @@ public class UserServiceTest {
|
|||||||
String email = "kok202@naver.com";
|
String email = "kok202@naver.com";
|
||||||
|
|
||||||
// when
|
// when
|
||||||
UserEntity result = userService.getByEmail(email);
|
User result = userService.getByEmail(email);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result.getNickname()).isEqualTo("kok202");
|
assertThat(result.getNickname()).isEqualTo("kok202");
|
||||||
@@ -55,7 +56,7 @@ public class UserServiceTest {
|
|||||||
// when
|
// when
|
||||||
// then
|
// then
|
||||||
assertThatThrownBy(() -> {
|
assertThatThrownBy(() -> {
|
||||||
UserEntity result = userService.getByEmail(email);
|
userService.getByEmail(email);
|
||||||
}).isInstanceOf(ResourceNotFoundException.class);
|
}).isInstanceOf(ResourceNotFoundException.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +64,7 @@ public class UserServiceTest {
|
|||||||
void getById는_ACTIVE_상태인_유저를_찾아올_수_있다() {
|
void getById는_ACTIVE_상태인_유저를_찾아올_수_있다() {
|
||||||
// given
|
// given
|
||||||
// when
|
// when
|
||||||
UserEntity result = userService.getById(1);
|
User result = userService.getById(1);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result.getNickname()).isEqualTo("kok202");
|
assertThat(result.getNickname()).isEqualTo("kok202");
|
||||||
@@ -75,14 +76,14 @@ public class UserServiceTest {
|
|||||||
// when
|
// when
|
||||||
// then
|
// then
|
||||||
assertThatThrownBy(() -> {
|
assertThatThrownBy(() -> {
|
||||||
UserEntity result = userService.getById(2);
|
userService.getById(2);
|
||||||
}).isInstanceOf(ResourceNotFoundException.class);
|
}).isInstanceOf(ResourceNotFoundException.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void userCreateDto_를_이용하여_유저를_생성할_수_있다() {
|
void userCreate_를_이용하여_유저를_생성할_수_있다() {
|
||||||
// given
|
// given
|
||||||
UserCreateDto userCreateDto = UserCreateDto.builder()
|
UserCreate userCreate = UserCreate.builder()
|
||||||
.email("kok202@kakao.com")
|
.email("kok202@kakao.com")
|
||||||
.address("Gyeongi")
|
.address("Gyeongi")
|
||||||
.nickname("kok202-k")
|
.nickname("kok202-k")
|
||||||
@@ -90,7 +91,7 @@ public class UserServiceTest {
|
|||||||
BDDMockito.doNothing().when(mailSender).send(any(SimpleMailMessage.class));
|
BDDMockito.doNothing().when(mailSender).send(any(SimpleMailMessage.class));
|
||||||
|
|
||||||
// when
|
// when
|
||||||
UserEntity result = userService.create(userCreateDto);
|
User result = userService.create(userCreate);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result.getId()).isNotNull();
|
assertThat(result.getId()).isNotNull();
|
||||||
@@ -101,19 +102,19 @@ public class UserServiceTest {
|
|||||||
@Test
|
@Test
|
||||||
void userUpdateDto_를_이용하여_유저를_수정할_수_있다() {
|
void userUpdateDto_를_이용하여_유저를_수정할_수_있다() {
|
||||||
// given
|
// given
|
||||||
UserUpdateDto userUpdateDto = UserUpdateDto.builder()
|
UserUpdate userUpdate = UserUpdate.builder()
|
||||||
.address("Incheon")
|
.address("Incheon")
|
||||||
.nickname("kok202-n")
|
.nickname("kok202-n")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
userService.update(1, userUpdateDto);
|
userService.update(1, userUpdate);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
UserEntity userEntity = userService.getById(1);
|
User user = userService.getById(1);
|
||||||
assertThat(userEntity.getId()).isNotNull();
|
assertThat(user.getId()).isNotNull();
|
||||||
assertThat(userEntity.getAddress()).isEqualTo("Incheon");
|
assertThat(user.getAddress()).isEqualTo("Incheon");
|
||||||
assertThat(userEntity.getNickname()).isEqualTo("kok202-n");
|
assertThat(user.getNickname()).isEqualTo("kok202-n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -123,8 +124,8 @@ public class UserServiceTest {
|
|||||||
userService.login(1);
|
userService.login(1);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
UserEntity userEntity = userService.getById(1);
|
User user = userService.getById(1);
|
||||||
assertThat(userEntity.getLastLoginAt()).isGreaterThan(0L);
|
assertThat(user.getLastLoginAt()).isGreaterThan(0L);
|
||||||
// assertThat(result.getLastLoginAt()).isEqualTo("T.T"); // FIXME
|
// assertThat(result.getLastLoginAt()).isEqualTo("T.T"); // FIXME
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,8 +136,8 @@ public class UserServiceTest {
|
|||||||
userService.verifyEmail(2, "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab");
|
userService.verifyEmail(2, "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab");
|
||||||
|
|
||||||
// then
|
// then
|
||||||
UserEntity userEntity = userService.getById(2);
|
User user = userService.getById(2);
|
||||||
assertThat(userEntity.getStatus()).isEqualTo(UserStatus.ACTIVE);
|
assertThat(user.getStatus()).isEqualTo(UserStatus.ACTIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
17
src/test/java/com/example/demo/mock/FakeMailSender.java
Normal file
17
src/test/java/com/example/demo/mock/FakeMailSender.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package com.example.demo.mock;
|
||||||
|
|
||||||
|
import com.example.demo.user.service.port.MailSender;
|
||||||
|
|
||||||
|
public class FakeMailSender implements MailSender {
|
||||||
|
|
||||||
|
public String email;
|
||||||
|
public String title;
|
||||||
|
public String content;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void send(String email, String title, String content) {
|
||||||
|
this.email = email;
|
||||||
|
this.title = title;
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
}
|
||||||
40
src/test/java/com/example/demo/mock/FakePostRepository.java
Normal file
40
src/test/java/com/example/demo/mock/FakePostRepository.java
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package com.example.demo.mock;
|
||||||
|
|
||||||
|
import com.example.demo.post.domain.Post;
|
||||||
|
import com.example.demo.post.service.port.PostRepository;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
public class FakePostRepository implements PostRepository {
|
||||||
|
|
||||||
|
private final AtomicLong autoGeneratedId = new AtomicLong(0);
|
||||||
|
private final List<Post> data = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Post> findById(long id) {
|
||||||
|
return data.stream().filter(item -> item.getId().equals(id)).findAny();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Post save(Post post) {
|
||||||
|
if (post.getId() == null || post.getId() == 0) {
|
||||||
|
Post newPost = Post.builder()
|
||||||
|
.id(autoGeneratedId.incrementAndGet())
|
||||||
|
.content(post.getContent())
|
||||||
|
.createdAt(post.getCreatedAt())
|
||||||
|
.modifiedAt(post.getModifiedAt())
|
||||||
|
.writer(post.getWriter())
|
||||||
|
.build();
|
||||||
|
data.add(newPost);
|
||||||
|
return newPost;
|
||||||
|
} else {
|
||||||
|
data.removeIf(item -> Objects.equals(item.getId(), post.getId()));
|
||||||
|
data.add(post);
|
||||||
|
return post;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
59
src/test/java/com/example/demo/mock/FakeUserRepository.java
Normal file
59
src/test/java/com/example/demo/mock/FakeUserRepository.java
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
package com.example.demo.mock;
|
||||||
|
|
||||||
|
import com.example.demo.common.domain.exception.ResourceNotFoundException;
|
||||||
|
import com.example.demo.user.domain.User;
|
||||||
|
import com.example.demo.user.domain.UserStatus;
|
||||||
|
import com.example.demo.user.service.port.UserRepository;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
public class FakeUserRepository implements UserRepository {
|
||||||
|
|
||||||
|
private final AtomicLong autoGeneratedId = new AtomicLong(0);
|
||||||
|
private final List<User> data = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User getById(long id) {
|
||||||
|
return findById(id).orElseThrow(() -> new ResourceNotFoundException("Users", id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<User> findById(long id) {
|
||||||
|
return data.stream().filter(item -> item.getId().equals(id)).findAny();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<User> findByIdAndStatus(long id, UserStatus userStatus) {
|
||||||
|
return data.stream().filter(item -> item.getId().equals(id) && item.getStatus() == userStatus).findAny();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<User> findByEmailAndStatus(String email, UserStatus userStatus) {
|
||||||
|
return data.stream().filter(item -> item.getEmail().equals(email) && item.getStatus() == userStatus).findAny();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User save(User user) {
|
||||||
|
if (user.getId() == null || user.getId() == 0) {
|
||||||
|
User newUser = User.builder()
|
||||||
|
.id(autoGeneratedId.incrementAndGet())
|
||||||
|
.email(user.getEmail())
|
||||||
|
.nickname(user.getNickname())
|
||||||
|
.address(user.getAddress())
|
||||||
|
.certificationCode(user.getCertificationCode())
|
||||||
|
.status(user.getStatus())
|
||||||
|
.lastLoginAt(user.getLastLoginAt())
|
||||||
|
.build();
|
||||||
|
data.add(newUser);
|
||||||
|
return newUser;
|
||||||
|
} else {
|
||||||
|
data.removeIf(item -> Objects.equals(item.getId(), user.getId()));
|
||||||
|
data.add(user);
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/test/java/com/example/demo/mock/TestClockHolder.java
Normal file
15
src/test/java/com/example/demo/mock/TestClockHolder.java
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package com.example.demo.mock;
|
||||||
|
|
||||||
|
import com.example.demo.common.service.port.ClockHolder;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class TestClockHolder implements ClockHolder {
|
||||||
|
|
||||||
|
private final long millis;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long millis() {
|
||||||
|
return millis;
|
||||||
|
}
|
||||||
|
}
|
||||||
65
src/test/java/com/example/demo/mock/TestContainer.java
Normal file
65
src/test/java/com/example/demo/mock/TestContainer.java
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
package com.example.demo.mock;
|
||||||
|
|
||||||
|
import com.example.demo.common.service.port.ClockHolder;
|
||||||
|
import com.example.demo.common.service.port.UuidHolder;
|
||||||
|
import com.example.demo.post.controller.PostController;
|
||||||
|
import com.example.demo.post.controller.PostCreateController;
|
||||||
|
import com.example.demo.post.controller.port.PostService;
|
||||||
|
import com.example.demo.post.service.PostServiceImpl;
|
||||||
|
import com.example.demo.post.service.port.PostRepository;
|
||||||
|
import com.example.demo.user.controller.MyInfoController;
|
||||||
|
import com.example.demo.user.controller.UserController;
|
||||||
|
import com.example.demo.user.controller.UserCreateController;
|
||||||
|
import com.example.demo.user.service.CertificationService;
|
||||||
|
import com.example.demo.user.service.UserServiceImpl;
|
||||||
|
import com.example.demo.user.service.port.MailSender;
|
||||||
|
import com.example.demo.user.service.port.UserRepository;
|
||||||
|
import lombok.Builder;
|
||||||
|
|
||||||
|
public class TestContainer {
|
||||||
|
|
||||||
|
public final MailSender mailSender;
|
||||||
|
public final UserRepository userRepository;
|
||||||
|
public final PostRepository postRepository;
|
||||||
|
public final PostService postService;
|
||||||
|
public final CertificationService certificationService;
|
||||||
|
public final UserController userController;
|
||||||
|
public final MyInfoController myInfoController;
|
||||||
|
public final UserCreateController userCreateController;
|
||||||
|
public final PostController postController;
|
||||||
|
public final PostCreateController postCreateController;
|
||||||
|
|
||||||
|
@Builder
|
||||||
|
public TestContainer(ClockHolder clockHolder, UuidHolder uuidHolder) {
|
||||||
|
this.mailSender = new FakeMailSender();
|
||||||
|
this.userRepository = new FakeUserRepository();
|
||||||
|
this.postRepository = new FakePostRepository();
|
||||||
|
this.postService = PostServiceImpl.builder()
|
||||||
|
.postRepository(this.postRepository)
|
||||||
|
.userRepository(this.userRepository)
|
||||||
|
.clockHolder(clockHolder)
|
||||||
|
.build();
|
||||||
|
this.certificationService = new CertificationService(this.mailSender);
|
||||||
|
UserServiceImpl userService = UserServiceImpl.builder()
|
||||||
|
.uuidHolder(uuidHolder)
|
||||||
|
.clockHolder(clockHolder)
|
||||||
|
.userRepository(this.userRepository)
|
||||||
|
.certificationService(this.certificationService)
|
||||||
|
.build();
|
||||||
|
this.userController = UserController.builder()
|
||||||
|
.userService(userService)
|
||||||
|
.build();
|
||||||
|
this.myInfoController = MyInfoController.builder()
|
||||||
|
.userService(userService)
|
||||||
|
.build();
|
||||||
|
this.userCreateController = UserCreateController.builder()
|
||||||
|
.userService(userService)
|
||||||
|
.build();
|
||||||
|
this.postController = PostController.builder()
|
||||||
|
.postService(postService)
|
||||||
|
.build();
|
||||||
|
this.postCreateController = PostCreateController.builder()
|
||||||
|
.postService(postService)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/test/java/com/example/demo/mock/TestUuidHolder.java
Normal file
15
src/test/java/com/example/demo/mock/TestUuidHolder.java
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package com.example.demo.mock;
|
||||||
|
|
||||||
|
import com.example.demo.common.service.port.UuidHolder;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class TestUuidHolder implements UuidHolder {
|
||||||
|
|
||||||
|
private final String uuid;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String random() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
package com.example.demo.post.controller;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||||
|
|
||||||
|
import com.example.demo.common.domain.exception.ResourceNotFoundException;
|
||||||
|
import com.example.demo.mock.TestContainer;
|
||||||
|
import com.example.demo.post.controller.response.PostResponse;
|
||||||
|
import com.example.demo.post.domain.Post;
|
||||||
|
import com.example.demo.post.domain.PostUpdate;
|
||||||
|
import com.example.demo.user.domain.User;
|
||||||
|
import com.example.demo.user.domain.UserStatus;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.http.HttpStatusCode;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
|
public class PostControllerTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void 사용자는_게시물을_단건_조회_할_수_있다() {
|
||||||
|
// given
|
||||||
|
TestContainer testContainer = TestContainer.builder()
|
||||||
|
.build();
|
||||||
|
User user = User.builder()
|
||||||
|
.id(1L)
|
||||||
|
.email("kok202@naver.com")
|
||||||
|
.nickname("kok202")
|
||||||
|
.address("Seoul")
|
||||||
|
.status(UserStatus.ACTIVE)
|
||||||
|
.certificationCode("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab")
|
||||||
|
.lastLoginAt(100L)
|
||||||
|
.build();
|
||||||
|
testContainer.userRepository.save(user);
|
||||||
|
testContainer.postRepository.save(Post.builder()
|
||||||
|
.id(1L)
|
||||||
|
.content("helloworld")
|
||||||
|
.writer(user)
|
||||||
|
.createdAt(100L)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
// when
|
||||||
|
ResponseEntity<PostResponse> result = testContainer.postController.getById(1L);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result.getStatusCode()).isEqualTo(HttpStatusCode.valueOf(200));
|
||||||
|
assertThat(result.getBody()).isNotNull();
|
||||||
|
assertThat(result.getBody().getContent()).isEqualTo("helloworld");
|
||||||
|
assertThat(result.getBody().getWriter().getNickname()).isEqualTo("kok202");
|
||||||
|
assertThat(result.getBody().getCreatedAt()).isEqualTo(100L);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void 사용자가_존재하지_않는_게시물을_조회할_경우_에러가_난다() throws Exception {
|
||||||
|
// given
|
||||||
|
TestContainer testContainer = TestContainer.builder()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
// then
|
||||||
|
assertThatThrownBy(() -> {
|
||||||
|
testContainer.postController.getById(1);
|
||||||
|
}).isInstanceOf(ResourceNotFoundException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void 사용자는_게시물을_수정할_수_있다() {
|
||||||
|
// given
|
||||||
|
TestContainer testContainer = TestContainer.builder()
|
||||||
|
.clockHolder(() -> 200L)
|
||||||
|
.build();
|
||||||
|
User user = User.builder()
|
||||||
|
.id(1L)
|
||||||
|
.email("kok202@naver.com")
|
||||||
|
.nickname("kok202")
|
||||||
|
.address("Seoul")
|
||||||
|
.status(UserStatus.ACTIVE)
|
||||||
|
.certificationCode("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab")
|
||||||
|
.lastLoginAt(100L)
|
||||||
|
.build();
|
||||||
|
testContainer.userRepository.save(user);
|
||||||
|
testContainer.postRepository.save(Post.builder()
|
||||||
|
.id(1L)
|
||||||
|
.content("helloworld")
|
||||||
|
.writer(user)
|
||||||
|
.createdAt(100L)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
// when
|
||||||
|
ResponseEntity<PostResponse> result = testContainer.postController.update(1L, PostUpdate.builder()
|
||||||
|
.content("foobar")
|
||||||
|
.build());
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result.getStatusCode()).isEqualTo(HttpStatusCode.valueOf(200));
|
||||||
|
assertThat(result.getBody()).isNotNull();
|
||||||
|
assertThat(result.getBody().getContent()).isEqualTo("foobar");
|
||||||
|
assertThat(result.getBody().getWriter().getNickname()).isEqualTo("kok202");
|
||||||
|
assertThat(result.getBody().getCreatedAt()).isEqualTo(100L);
|
||||||
|
assertThat(result.getBody().getModifiedAt()).isEqualTo(200L);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package com.example.demo.post.controller;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||||
|
|
||||||
|
import com.example.demo.mock.TestContainer;
|
||||||
|
import com.example.demo.post.controller.response.PostResponse;
|
||||||
|
import com.example.demo.post.domain.PostCreate;
|
||||||
|
import com.example.demo.user.domain.User;
|
||||||
|
import com.example.demo.user.domain.UserStatus;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.http.HttpStatusCode;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
|
public class PostCreateControllerTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void 사용자는_게시물을_작성할_수_있다() {
|
||||||
|
// given
|
||||||
|
TestContainer testContainer = TestContainer.builder()
|
||||||
|
.clockHolder(() -> 1679530673958L)
|
||||||
|
.build();
|
||||||
|
testContainer.userRepository.save(User.builder()
|
||||||
|
.id(1L)
|
||||||
|
.email("kok202@naver.com")
|
||||||
|
.nickname("kok202")
|
||||||
|
.address("Seoul")
|
||||||
|
.status(UserStatus.ACTIVE)
|
||||||
|
.certificationCode("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab")
|
||||||
|
.lastLoginAt(100L)
|
||||||
|
.build());
|
||||||
|
PostCreate postCreate = PostCreate.builder()
|
||||||
|
.writerId(1)
|
||||||
|
.content("helloworld")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
ResponseEntity<PostResponse> result = testContainer.postCreateController.create(postCreate);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result.getStatusCode()).isEqualTo(HttpStatusCode.valueOf(201));
|
||||||
|
assertThat(result.getBody()).isNotNull();
|
||||||
|
assertThat(result.getBody().getContent()).isEqualTo("helloworld");
|
||||||
|
assertThat(result.getBody().getWriter().getNickname()).isEqualTo("kok202");
|
||||||
|
assertThat(result.getBody().getCreatedAt()).isEqualTo(1679530673958L);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.example.demo.post.controller.response;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
|
|
||||||
|
import com.example.demo.post.domain.Post;
|
||||||
|
import com.example.demo.user.domain.User;
|
||||||
|
import com.example.demo.user.domain.UserStatus;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class PostResponseTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void Post로_응답을_생성할_수_있다() {
|
||||||
|
// given
|
||||||
|
Post post = Post.builder()
|
||||||
|
.content("helloworld")
|
||||||
|
.writer(User.builder()
|
||||||
|
.email("kok202@naver.com")
|
||||||
|
.nickname("kok202")
|
||||||
|
.address("Seoul")
|
||||||
|
.status(UserStatus.ACTIVE)
|
||||||
|
.certificationCode("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab")
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
PostResponse postResponse = PostResponse.from(post);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(postResponse.getContent()).isEqualTo("helloworld");
|
||||||
|
assertThat(postResponse.getWriter().getEmail()).isEqualTo("kok202@naver.com");
|
||||||
|
assertThat(postResponse.getWriter().getNickname()).isEqualTo("kok202");
|
||||||
|
assertThat(postResponse.getWriter().getStatus()).isEqualTo(UserStatus.ACTIVE);
|
||||||
|
}
|
||||||
|
}
|
||||||
69
src/test/java/com/example/demo/post/domain/PostTest.java
Normal file
69
src/test/java/com/example/demo/post/domain/PostTest.java
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
package com.example.demo.post.domain;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
|
|
||||||
|
import com.example.demo.mock.TestClockHolder;
|
||||||
|
import com.example.demo.user.domain.User;
|
||||||
|
import com.example.demo.user.domain.UserStatus;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class PostTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void PostCreate으로_게시물을_만들_수_있다() {
|
||||||
|
// given
|
||||||
|
PostCreate postCreate = PostCreate.builder()
|
||||||
|
.writerId(1)
|
||||||
|
.content("helloworld")
|
||||||
|
.build();
|
||||||
|
User writer = User.builder()
|
||||||
|
.id(1L)
|
||||||
|
.email("kok202@naver.com")
|
||||||
|
.nickname("kok202")
|
||||||
|
.address("Seoul")
|
||||||
|
.status(UserStatus.ACTIVE)
|
||||||
|
.certificationCode("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
Post post = Post.from(writer, postCreate, new TestClockHolder(1679530673958L));
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(post.getContent()).isEqualTo("helloworld");
|
||||||
|
assertThat(post.getCreatedAt()).isEqualTo(1679530673958L);
|
||||||
|
assertThat(post.getWriter().getEmail()).isEqualTo("kok202@naver.com");
|
||||||
|
assertThat(post.getWriter().getNickname()).isEqualTo("kok202");
|
||||||
|
assertThat(post.getWriter().getAddress()).isEqualTo("Seoul");
|
||||||
|
assertThat(post.getWriter().getStatus()).isEqualTo(UserStatus.ACTIVE);
|
||||||
|
assertThat(post.getWriter().getCertificationCode()).isEqualTo("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab");
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void PostUpdate로_게시물을_수정할_수_있다() {
|
||||||
|
// given
|
||||||
|
PostUpdate postUpdate = PostUpdate.builder()
|
||||||
|
.content("foobar")
|
||||||
|
.build();
|
||||||
|
User writer = User.builder()
|
||||||
|
.id(1L)
|
||||||
|
.email("kok202@naver.com")
|
||||||
|
.nickname("kok202")
|
||||||
|
.address("Seoul")
|
||||||
|
.status(UserStatus.ACTIVE)
|
||||||
|
.certificationCode("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab")
|
||||||
|
.build();
|
||||||
|
Post post = Post.builder()
|
||||||
|
.id(1L)
|
||||||
|
.content("helloworld")
|
||||||
|
.createdAt(1678530673958L)
|
||||||
|
.modifiedAt(0L)
|
||||||
|
.writer(writer)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
post = post.update(postUpdate, new TestClockHolder(1679530673958L));
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(post.getContent()).isEqualTo("foobar");
|
||||||
|
assertThat(post.getModifiedAt()).isEqualTo(1679530673958L);
|
||||||
|
}
|
||||||
|
}
|
||||||
102
src/test/java/com/example/demo/post/service/PostServiceTest.java
Normal file
102
src/test/java/com/example/demo/post/service/PostServiceTest.java
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
package com.example.demo.post.service;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
|
|
||||||
|
import com.example.demo.mock.FakePostRepository;
|
||||||
|
import com.example.demo.mock.FakeUserRepository;
|
||||||
|
import com.example.demo.mock.TestClockHolder;
|
||||||
|
import com.example.demo.post.domain.Post;
|
||||||
|
import com.example.demo.post.domain.PostCreate;
|
||||||
|
import com.example.demo.post.domain.PostUpdate;
|
||||||
|
import com.example.demo.user.domain.User;
|
||||||
|
import com.example.demo.user.domain.UserStatus;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class PostServiceTest {
|
||||||
|
|
||||||
|
private PostServiceImpl postService;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void init() {
|
||||||
|
FakePostRepository fakePostRepository = new FakePostRepository();
|
||||||
|
FakeUserRepository fakeUserRepository = new FakeUserRepository();
|
||||||
|
this.postService = PostServiceImpl.builder()
|
||||||
|
.postRepository(fakePostRepository)
|
||||||
|
.userRepository(fakeUserRepository)
|
||||||
|
.clockHolder(new TestClockHolder(1679530673958L))
|
||||||
|
.build();
|
||||||
|
User user1 = User.builder()
|
||||||
|
.id(1L)
|
||||||
|
.email("kok202@naver.com")
|
||||||
|
.nickname("kok202")
|
||||||
|
.address("Seoul")
|
||||||
|
.certificationCode("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")
|
||||||
|
.status(UserStatus.ACTIVE)
|
||||||
|
.lastLoginAt(0L)
|
||||||
|
.build();
|
||||||
|
User user2 = User.builder()
|
||||||
|
.id(2L)
|
||||||
|
.email("kok303@naver.com")
|
||||||
|
.nickname("kok303")
|
||||||
|
.address("Seoul")
|
||||||
|
.certificationCode("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab")
|
||||||
|
.status(UserStatus.PENDING)
|
||||||
|
.lastLoginAt(0L)
|
||||||
|
.build();
|
||||||
|
fakeUserRepository.save(user1);
|
||||||
|
fakeUserRepository.save(user2);
|
||||||
|
fakePostRepository.save(Post.builder()
|
||||||
|
.id(1L)
|
||||||
|
.content("helloworld")
|
||||||
|
.createdAt(1678530673958L)
|
||||||
|
.modifiedAt(0L)
|
||||||
|
.writer(user1)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getById는_존재하는_게시물을_내려준다() {
|
||||||
|
// given
|
||||||
|
// when
|
||||||
|
Post result = postService.getById(1);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result.getContent()).isEqualTo("helloworld");
|
||||||
|
assertThat(result.getWriter().getEmail()).isEqualTo("kok202@naver.com");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void postCreateDto_를_이용하여_게시물을_생성할_수_있다() {
|
||||||
|
// given
|
||||||
|
PostCreate postCreate = PostCreate.builder()
|
||||||
|
.writerId(1)
|
||||||
|
.content("foobar")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
Post result = postService.create(postCreate);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result.getId()).isNotNull();
|
||||||
|
assertThat(result.getContent()).isEqualTo("foobar");
|
||||||
|
assertThat(result.getCreatedAt()).isEqualTo(1679530673958L);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void postUpdateDto_를_이용하여_게시물을_수정할_수_있다() {
|
||||||
|
// given
|
||||||
|
PostUpdate postUpdate = PostUpdate.builder()
|
||||||
|
.content("hello world :)")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
postService.update(1, postUpdate);
|
||||||
|
|
||||||
|
// then
|
||||||
|
Post post = postService.getById(1);
|
||||||
|
assertThat(post.getContent()).isEqualTo("hello world :)");
|
||||||
|
assertThat(post.getModifiedAt()).isEqualTo(1679530673958L);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package com.example.demo.user.controller;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
|
||||||
|
|
||||||
|
import com.example.demo.mock.TestContainer;
|
||||||
|
import com.example.demo.user.controller.response.MyProfileResponse;
|
||||||
|
import com.example.demo.user.domain.User;
|
||||||
|
import com.example.demo.user.domain.UserStatus;
|
||||||
|
import com.example.demo.user.domain.UserUpdate;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.http.HttpStatusCode;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
|
public class MyInfoControllerTest {
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void 사용자는_내_정보를_불러올_때_개인정보인_주소도_갖고_올_수_있다() {
|
||||||
|
// given
|
||||||
|
TestContainer testContainer = TestContainer.builder()
|
||||||
|
.clockHolder(() -> 1678530673958L)
|
||||||
|
.build();
|
||||||
|
testContainer.userRepository.save(User.builder()
|
||||||
|
.id(1L)
|
||||||
|
.email("kok202@naver.com")
|
||||||
|
.nickname("kok202")
|
||||||
|
.address("Seoul")
|
||||||
|
.status(UserStatus.ACTIVE)
|
||||||
|
.certificationCode("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab")
|
||||||
|
.lastLoginAt(100L)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
// when
|
||||||
|
ResponseEntity<MyProfileResponse> result = testContainer.myInfoController.get("kok202@naver.com");
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result.getStatusCode()).isEqualTo(HttpStatusCode.valueOf(200));
|
||||||
|
assertThat(result.getBody()).isNotNull();
|
||||||
|
assertThat(result.getBody().getEmail()).isEqualTo("kok202@naver.com");
|
||||||
|
assertThat(result.getBody().getNickname()).isEqualTo("kok202");
|
||||||
|
assertThat(result.getBody().getLastLoginAt()).isEqualTo(1678530673958L);
|
||||||
|
assertThat(result.getBody().getAddress()).isEqualTo("Seoul");
|
||||||
|
assertThat(result.getBody().getStatus()).isEqualTo(UserStatus.ACTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void 사용자는_내_정보를_수정할_수_있다() {
|
||||||
|
// given
|
||||||
|
TestContainer testContainer = TestContainer.builder()
|
||||||
|
.build();
|
||||||
|
testContainer.userRepository.save(User.builder()
|
||||||
|
.id(1L)
|
||||||
|
.email("kok202@naver.com")
|
||||||
|
.nickname("kok202")
|
||||||
|
.address("Seoul")
|
||||||
|
.status(UserStatus.ACTIVE)
|
||||||
|
.certificationCode("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab")
|
||||||
|
.lastLoginAt(100L)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
// when
|
||||||
|
ResponseEntity<MyProfileResponse> result = testContainer.myInfoController.update("kok202@naver.com", UserUpdate.builder()
|
||||||
|
.address("Pangyo")
|
||||||
|
.nickname("kok202-n")
|
||||||
|
.build());
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result.getStatusCode()).isEqualTo(HttpStatusCode.valueOf(200));
|
||||||
|
assertThat(result.getBody()).isNotNull();
|
||||||
|
assertThat(result.getBody().getEmail()).isEqualTo("kok202@naver.com");
|
||||||
|
assertThat(result.getBody().getNickname()).isEqualTo("kok202-n");
|
||||||
|
assertThat(result.getBody().getLastLoginAt()).isEqualTo(100);
|
||||||
|
assertThat(result.getBody().getAddress()).isEqualTo("Pangyo");
|
||||||
|
assertThat(result.getBody().getStatus()).isEqualTo(UserStatus.ACTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
package com.example.demo.user.controller;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||||
|
|
||||||
|
import com.example.demo.common.domain.exception.CertificationCodeNotMatchedException;
|
||||||
|
import com.example.demo.common.domain.exception.ResourceNotFoundException;
|
||||||
|
import com.example.demo.mock.TestContainer;
|
||||||
|
import com.example.demo.user.controller.response.MyProfileResponse;
|
||||||
|
import com.example.demo.user.controller.response.UserResponse;
|
||||||
|
import com.example.demo.user.domain.User;
|
||||||
|
import com.example.demo.user.domain.UserStatus;
|
||||||
|
import com.example.demo.user.domain.UserUpdate;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.http.HttpStatusCode;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
|
public class UserControllerTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void 사용자는_특정_유저의_정보를_개인정보는_소거된채_전달_받을_수_있다() {
|
||||||
|
// given
|
||||||
|
TestContainer testContainer = TestContainer.builder()
|
||||||
|
.build();
|
||||||
|
testContainer.userRepository.save(User.builder()
|
||||||
|
.id(1L)
|
||||||
|
.email("kok202@naver.com")
|
||||||
|
.nickname("kok202")
|
||||||
|
.address("Seoul")
|
||||||
|
.status(UserStatus.ACTIVE)
|
||||||
|
.certificationCode("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab")
|
||||||
|
.lastLoginAt(100L)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
// when
|
||||||
|
ResponseEntity<UserResponse> result = testContainer.userController.getById(1);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result.getStatusCode()).isEqualTo(HttpStatusCode.valueOf(200));
|
||||||
|
assertThat(result.getBody()).isNotNull();
|
||||||
|
assertThat(result.getBody().getEmail()).isEqualTo("kok202@naver.com");
|
||||||
|
assertThat(result.getBody().getNickname()).isEqualTo("kok202");
|
||||||
|
assertThat(result.getBody().getLastLoginAt()).isEqualTo(100);
|
||||||
|
assertThat(result.getBody().getStatus()).isEqualTo(UserStatus.ACTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void 사용자는_존재하지_않는_유저의_아이디로_api_호출할_경우_404_응답을_받는다() {
|
||||||
|
// given
|
||||||
|
TestContainer testContainer = TestContainer.builder()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
// then
|
||||||
|
assertThatThrownBy(() -> {
|
||||||
|
testContainer.userController.getById(1);
|
||||||
|
}).isInstanceOf(ResourceNotFoundException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void 사용자는_인증_코드로_계정을_활성화_시킬_수_있다() {
|
||||||
|
// given
|
||||||
|
TestContainer testContainer = TestContainer.builder()
|
||||||
|
.build();
|
||||||
|
testContainer.userRepository.save(User.builder()
|
||||||
|
.id(1L)
|
||||||
|
.email("kok202@naver.com")
|
||||||
|
.nickname("kok202")
|
||||||
|
.address("Seoul")
|
||||||
|
.status(UserStatus.PENDING)
|
||||||
|
.certificationCode("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab")
|
||||||
|
.lastLoginAt(100L)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
// when
|
||||||
|
ResponseEntity<Void> result = testContainer.userController.verifyEmail(1, "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab");
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result.getStatusCode()).isEqualTo(HttpStatusCode.valueOf(302));
|
||||||
|
assertThat(testContainer.userRepository.getById(1).getStatus()).isEqualTo(UserStatus.ACTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void 사용자는_인증_코드가_일치하지_않을_경우_권한_없음_에러를_내려준다() {
|
||||||
|
// given
|
||||||
|
TestContainer testContainer = TestContainer.builder()
|
||||||
|
.build();
|
||||||
|
testContainer.userRepository.save(User.builder()
|
||||||
|
.id(1L)
|
||||||
|
.email("kok202@naver.com")
|
||||||
|
.nickname("kok202")
|
||||||
|
.address("Seoul")
|
||||||
|
.status(UserStatus.PENDING)
|
||||||
|
.certificationCode("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab")
|
||||||
|
.lastLoginAt(100L)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
// when
|
||||||
|
assertThatThrownBy(() -> {
|
||||||
|
testContainer.userController.verifyEmail(1, "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaac");
|
||||||
|
}).isInstanceOf(CertificationCodeNotMatchedException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package com.example.demo.user.controller;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||||
|
|
||||||
|
import com.example.demo.mock.TestContainer;
|
||||||
|
import com.example.demo.user.controller.response.UserResponse;
|
||||||
|
import com.example.demo.user.domain.UserCreate;
|
||||||
|
import com.example.demo.user.domain.UserStatus;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.http.HttpStatusCode;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
|
public class UserCreateControllerTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void 사용자는_회원_가입을_할_수있고_회원가입된_사용자는_PENDING_상태이다() {
|
||||||
|
// given
|
||||||
|
TestContainer testContainer = TestContainer.builder()
|
||||||
|
.uuidHolder(() -> "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab")
|
||||||
|
.build();
|
||||||
|
UserCreate userCreate = UserCreate.builder()
|
||||||
|
.email("kok202@kakao.com")
|
||||||
|
.nickname("kok202")
|
||||||
|
.address("Pangyo")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
ResponseEntity<UserResponse> result = testContainer.userCreateController.create(userCreate);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result.getStatusCode()).isEqualTo(HttpStatusCode.valueOf(201));
|
||||||
|
assertThat(result.getBody()).isNotNull();
|
||||||
|
assertThat(result.getBody().getEmail()).isEqualTo("kok202@kakao.com");
|
||||||
|
assertThat(result.getBody().getNickname()).isEqualTo("kok202");
|
||||||
|
assertThat(result.getBody().getLastLoginAt()).isNull();
|
||||||
|
assertThat(result.getBody().getStatus()).isEqualTo(UserStatus.PENDING);
|
||||||
|
assertThat(testContainer.userRepository.getById(1).getCertificationCode()).isEqualTo("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.example.demo.user.controller.response;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
|
|
||||||
|
import com.example.demo.user.domain.User;
|
||||||
|
import com.example.demo.user.domain.UserStatus;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class MyProfileResponseTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void User으로_응답을_생성할_수_있다() {
|
||||||
|
// given
|
||||||
|
User user = User.builder()
|
||||||
|
.id(1L)
|
||||||
|
.email("kok202@naver.com")
|
||||||
|
.nickname("kok202")
|
||||||
|
.address("Seoul")
|
||||||
|
.status(UserStatus.ACTIVE)
|
||||||
|
.lastLoginAt(100L)
|
||||||
|
.certificationCode("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
MyProfileResponse myProfileResponse = MyProfileResponse.from(user);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(myProfileResponse.getId()).isEqualTo(1);
|
||||||
|
assertThat(myProfileResponse.getEmail()).isEqualTo("kok202@naver.com");
|
||||||
|
assertThat(myProfileResponse.getAddress()).isEqualTo("Seoul");
|
||||||
|
assertThat(myProfileResponse.getStatus()).isEqualTo(UserStatus.ACTIVE);
|
||||||
|
assertThat(myProfileResponse.getLastLoginAt()).isEqualTo(100L);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package com.example.demo.user.controller.response;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
|
|
||||||
|
import com.example.demo.user.domain.User;
|
||||||
|
import com.example.demo.user.domain.UserStatus;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class UserResponseTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void User으로_응답을_생성할_수_있다() {
|
||||||
|
// given
|
||||||
|
User user = User.builder()
|
||||||
|
.id(1L)
|
||||||
|
.email("kok202@naver.com")
|
||||||
|
.nickname("kok202")
|
||||||
|
.address("Seoul")
|
||||||
|
.status(UserStatus.ACTIVE)
|
||||||
|
.lastLoginAt(100L)
|
||||||
|
.certificationCode("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
UserResponse userResponse = UserResponse.from(user);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(userResponse.getId()).isEqualTo(1);
|
||||||
|
assertThat(userResponse.getEmail()).isEqualTo("kok202@naver.com");
|
||||||
|
assertThat(userResponse.getStatus()).isEqualTo(UserStatus.ACTIVE);
|
||||||
|
assertThat(userResponse.getLastLoginAt()).isEqualTo(100L);
|
||||||
|
}
|
||||||
|
}
|
||||||
122
src/test/java/com/example/demo/user/domain/UserTest.java
Normal file
122
src/test/java/com/example/demo/user/domain/UserTest.java
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
package com.example.demo.user.domain;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
|
||||||
|
|
||||||
|
import com.example.demo.common.domain.exception.CertificationCodeNotMatchedException;
|
||||||
|
import com.example.demo.mock.TestClockHolder;
|
||||||
|
import com.example.demo.mock.TestUuidHolder;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class UserTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void UserCreate_객체로_생성할_수_있다() {
|
||||||
|
// given
|
||||||
|
UserCreate userCreate = UserCreate.builder()
|
||||||
|
.email("kok202@kakao.com")
|
||||||
|
.nickname("kok202")
|
||||||
|
.address("Pangyo")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
User user = User.from(userCreate, new TestUuidHolder("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"));
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(user.getId()).isNull();
|
||||||
|
assertThat(user.getEmail()).isEqualTo("kok202@kakao.com");
|
||||||
|
assertThat(user.getNickname()).isEqualTo("kok202");
|
||||||
|
assertThat(user.getAddress()).isEqualTo("Pangyo");
|
||||||
|
assertThat(user.getStatus()).isEqualTo(UserStatus.PENDING);
|
||||||
|
assertThat(user.getCertificationCode()).isEqualTo("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void UserUpdate_객체로_데이터를_업데이트_할_수_있다() {
|
||||||
|
// given
|
||||||
|
User user = User.builder()
|
||||||
|
.id(1L)
|
||||||
|
.email("kok202@kakao.com")
|
||||||
|
.nickname("kok202")
|
||||||
|
.address("Seoul")
|
||||||
|
.status(UserStatus.ACTIVE)
|
||||||
|
.lastLoginAt(100L)
|
||||||
|
.certificationCode("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")
|
||||||
|
.build();
|
||||||
|
UserUpdate userUpdate = UserUpdate.builder()
|
||||||
|
.nickname("kok202-k")
|
||||||
|
.address("Pangyo")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
user = user.update(userUpdate);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(user.getId()).isEqualTo(1L);
|
||||||
|
assertThat(user.getEmail()).isEqualTo("kok202@kakao.com");
|
||||||
|
assertThat(user.getNickname()).isEqualTo("kok202-k");
|
||||||
|
assertThat(user.getAddress()).isEqualTo("Pangyo");
|
||||||
|
assertThat(user.getStatus()).isEqualTo(UserStatus.ACTIVE);
|
||||||
|
assertThat(user.getCertificationCode()).isEqualTo("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa");
|
||||||
|
assertThat(user.getLastLoginAt()).isEqualTo(100L);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void 로그인을_할_수_있고_로그인시_마지막_로그인_시간이_변경된다() {
|
||||||
|
// given
|
||||||
|
User user = User.builder()
|
||||||
|
.id(1L)
|
||||||
|
.email("kok202@kakao.com")
|
||||||
|
.nickname("kok202")
|
||||||
|
.address("Seoul")
|
||||||
|
.status(UserStatus.ACTIVE)
|
||||||
|
.lastLoginAt(100L)
|
||||||
|
.certificationCode("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
user = user.login(new TestClockHolder(1678530673958L));
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(user.getLastLoginAt()).isEqualTo(1678530673958L);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void 유효한_인증_코드로_계정을_활성화_할_수_있다() {
|
||||||
|
// given
|
||||||
|
User user = User.builder()
|
||||||
|
.id(1L)
|
||||||
|
.email("kok202@kakao.com")
|
||||||
|
.nickname("kok202")
|
||||||
|
.address("Seoul")
|
||||||
|
.status(UserStatus.PENDING)
|
||||||
|
.lastLoginAt(100L)
|
||||||
|
.certificationCode("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
user = user.certificate("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa");
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(user.getStatus()).isEqualTo(UserStatus.ACTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void 잘못된_인증_코드로_계정을_활성화_하려하면_에러를_던진다() {
|
||||||
|
// given
|
||||||
|
User user = User.builder()
|
||||||
|
.id(1L)
|
||||||
|
.email("kok202@kakao.com")
|
||||||
|
.nickname("kok202")
|
||||||
|
.address("Seoul")
|
||||||
|
.status(UserStatus.PENDING)
|
||||||
|
.lastLoginAt(100L)
|
||||||
|
.certificationCode("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
// then
|
||||||
|
assertThatThrownBy(() -> user.certificate("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab"))
|
||||||
|
.isInstanceOf(CertificationCodeNotMatchedException.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.example.demo.user.service;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
|
|
||||||
|
import com.example.demo.mock.FakeMailSender;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class CertificationServiceTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void 이메일과_컨텐츠가_제대로_만들어져서_보내지는지_테스트한다() {
|
||||||
|
// given
|
||||||
|
FakeMailSender fakeMailSender = new FakeMailSender();
|
||||||
|
CertificationService certificationService = new CertificationService(fakeMailSender);
|
||||||
|
|
||||||
|
// when
|
||||||
|
certificationService.send("kok202@naver.com", 1, "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa");
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(fakeMailSender.email).isEqualTo("kok202@naver.com");
|
||||||
|
assertThat(fakeMailSender.title).isEqualTo("Please certify your email address");
|
||||||
|
assertThat(fakeMailSender.content).isEqualTo(
|
||||||
|
"Please click the following link to certify your email address: http://localhost:8080/api/users/1/verify?certificationCode=aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa");
|
||||||
|
}
|
||||||
|
}
|
||||||
166
src/test/java/com/example/demo/user/service/UserServiceTest.java
Normal file
166
src/test/java/com/example/demo/user/service/UserServiceTest.java
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
package com.example.demo.user.service;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
|
||||||
|
import com.example.demo.common.domain.exception.CertificationCodeNotMatchedException;
|
||||||
|
import com.example.demo.common.domain.exception.ResourceNotFoundException;
|
||||||
|
import com.example.demo.mock.FakeMailSender;
|
||||||
|
import com.example.demo.mock.FakeUserRepository;
|
||||||
|
import com.example.demo.mock.TestClockHolder;
|
||||||
|
import com.example.demo.mock.TestUuidHolder;
|
||||||
|
import com.example.demo.user.domain.User;
|
||||||
|
import com.example.demo.user.domain.UserCreate;
|
||||||
|
import com.example.demo.user.domain.UserStatus;
|
||||||
|
import com.example.demo.user.domain.UserUpdate;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class UserServiceTest {
|
||||||
|
|
||||||
|
private UserServiceImpl userService;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void init() {
|
||||||
|
FakeMailSender fakeMailSender = new FakeMailSender();
|
||||||
|
FakeUserRepository fakeUserRepository = new FakeUserRepository();
|
||||||
|
this.userService = UserServiceImpl.builder()
|
||||||
|
.uuidHolder(new TestUuidHolder("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab"))
|
||||||
|
.clockHolder(new TestClockHolder(1678530673958L))
|
||||||
|
.userRepository(fakeUserRepository)
|
||||||
|
.certificationService(new CertificationService(fakeMailSender))
|
||||||
|
.build();
|
||||||
|
fakeUserRepository.save(User.builder()
|
||||||
|
.id(1L)
|
||||||
|
.email("kok202@naver.com")
|
||||||
|
.nickname("kok202")
|
||||||
|
.address("Seoul")
|
||||||
|
.certificationCode("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")
|
||||||
|
.status(UserStatus.ACTIVE)
|
||||||
|
.lastLoginAt(0L)
|
||||||
|
.build());
|
||||||
|
fakeUserRepository.save(User.builder()
|
||||||
|
.id(2L)
|
||||||
|
.email("kok303@naver.com")
|
||||||
|
.nickname("kok303")
|
||||||
|
.address("Seoul")
|
||||||
|
.certificationCode("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab")
|
||||||
|
.status(UserStatus.PENDING)
|
||||||
|
.lastLoginAt(0L)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getByEmail은_ACTIVE_상태인_유저를_찾아올_수_있다() {
|
||||||
|
// given
|
||||||
|
String email = "kok202@naver.com";
|
||||||
|
|
||||||
|
// when
|
||||||
|
User result = userService.getByEmail(email);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result.getNickname()).isEqualTo("kok202");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getByEmail은_PENDING_상태인_유저는_찾아올_수_없다() {
|
||||||
|
// given
|
||||||
|
String email = "kok303@naver.com";
|
||||||
|
|
||||||
|
// when
|
||||||
|
// then
|
||||||
|
assertThatThrownBy(() -> {
|
||||||
|
userService.getByEmail(email);
|
||||||
|
}).isInstanceOf(ResourceNotFoundException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getById는_ACTIVE_상태인_유저를_찾아올_수_있다() {
|
||||||
|
// given
|
||||||
|
// when
|
||||||
|
User result = userService.getById(1);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result.getNickname()).isEqualTo("kok202");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getById는_PENDING_상태인_유저는_찾아올_수_없다() {
|
||||||
|
// given
|
||||||
|
// when
|
||||||
|
// then
|
||||||
|
assertThatThrownBy(() -> {
|
||||||
|
userService.getById(2);
|
||||||
|
}).isInstanceOf(ResourceNotFoundException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void userCreate_를_이용하여_유저를_생성할_수_있다() {
|
||||||
|
// given
|
||||||
|
UserCreate userCreate = UserCreate.builder()
|
||||||
|
.email("kok202@kakao.com")
|
||||||
|
.address("Gyeongi")
|
||||||
|
.nickname("kok202-k")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
User result = userService.create(userCreate);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result.getId()).isNotNull();
|
||||||
|
assertThat(result.getStatus()).isEqualTo(UserStatus.PENDING);
|
||||||
|
assertThat(result.getCertificationCode()).isEqualTo("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void userUpdateDto_를_이용하여_유저를_수정할_수_있다() {
|
||||||
|
// given
|
||||||
|
UserUpdate userUpdate = UserUpdate.builder()
|
||||||
|
.address("Incheon")
|
||||||
|
.nickname("kok202-n")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
userService.update(1, userUpdate);
|
||||||
|
|
||||||
|
// then
|
||||||
|
User user = userService.getById(1);
|
||||||
|
assertThat(user.getId()).isNotNull();
|
||||||
|
assertThat(user.getAddress()).isEqualTo("Incheon");
|
||||||
|
assertThat(user.getNickname()).isEqualTo("kok202-n");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void user를_로그인_시키면_마지막_로그인_시간이_변경된다() {
|
||||||
|
// given
|
||||||
|
// when
|
||||||
|
userService.login(1);
|
||||||
|
|
||||||
|
// then
|
||||||
|
User user = userService.getById(1);
|
||||||
|
assertThat(user.getLastLoginAt()).isEqualTo(1678530673958L);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void PENDING_상태의_사용자는_인증_코드로_ACTIVE_시킬_수_있다() {
|
||||||
|
// given
|
||||||
|
// when
|
||||||
|
userService.verifyEmail(2, "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab");
|
||||||
|
|
||||||
|
// then
|
||||||
|
User user = userService.getById(2);
|
||||||
|
assertThat(user.getStatus()).isEqualTo(UserStatus.ACTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void PENDING_상태의_사용자는_잘못된_인증_코드를_받으면_에러를_던진다() {
|
||||||
|
// given
|
||||||
|
// when
|
||||||
|
// then
|
||||||
|
assertThatThrownBy(() -> {
|
||||||
|
userService.verifyEmail(2, "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaac");
|
||||||
|
}).isInstanceOf(CertificationCodeNotMatchedException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user