Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73453defa5 | ||
|
|
435de08537 |
@@ -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.NOT_FOUND;
|
||||
|
||||
import com.example.demo.exception.CertificationCodeNotMatchedException;
|
||||
import com.example.demo.exception.ResourceNotFoundException;
|
||||
import com.example.demo.common.domain.exception.CertificationCodeNotMatchedException;
|
||||
import com.example.demo.common.domain.exception.ResourceNotFoundException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.core.Ordered;
|
||||
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 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 {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.demo.exception;
|
||||
package com.example.demo.common.domain.exception;
|
||||
|
||||
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.getPostById(id)));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public ResponseEntity<PostResponse> updatePost(@PathVariable long id, @RequestBody PostUpdateDto postUpdateDto) {
|
||||
return ResponseEntity
|
||||
.ok()
|
||||
.body(toResponse(postService.updatePost(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.getByIdOrElseThrow(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.updateUser(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.model.dto.PostResponse;
|
||||
import com.example.demo.service.PostService;
|
||||
import com.example.demo.post.controller.port.PostService;
|
||||
import com.example.demo.post.controller.response.PostResponse;
|
||||
import com.example.demo.post.domain.PostCreate;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.Builder;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -15,16 +16,16 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
@Tag(name = "게시물(posts)")
|
||||
@RestController
|
||||
@RequestMapping("/api/posts")
|
||||
@Builder
|
||||
@RequiredArgsConstructor
|
||||
public class PostCreateController {
|
||||
|
||||
private final PostService postService;
|
||||
private final PostController postController;
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<PostResponse> createPost(@RequestBody PostCreateDto postCreateDto) {
|
||||
public ResponseEntity<PostResponse> create(@RequestBody PostCreate postCreate) {
|
||||
return ResponseEntity
|
||||
.status(HttpStatus.CREATED)
|
||||
.body(postController.toResponse(postService.createPost(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 lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class PostCreateDto {
|
||||
public class PostCreate {
|
||||
|
||||
private final long writerId;
|
||||
private final String content;
|
||||
|
||||
@Builder
|
||||
public PostCreateDto(
|
||||
public PostCreate(
|
||||
@JsonProperty("writerId") long writerId,
|
||||
@JsonProperty("content") String content) {
|
||||
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 lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class PostUpdateDto {
|
||||
public class PostUpdate {
|
||||
|
||||
private final String content;
|
||||
|
||||
@Builder
|
||||
public PostUpdateDto(
|
||||
public PostUpdate(
|
||||
@JsonProperty("content") String 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 getPostById(long id) {
|
||||
return postRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("Posts", id));
|
||||
}
|
||||
|
||||
public PostEntity createPost(PostCreateDto postCreateDto) {
|
||||
UserEntity userEntity = userService.getByIdOrElseThrow(postCreateDto.getWriterId());
|
||||
PostEntity postEntity = new PostEntity();
|
||||
postEntity.setWriter(userEntity);
|
||||
postEntity.setContent(postCreateDto.getContent());
|
||||
postEntity.setCreatedAt(Clock.systemUTC().millis());
|
||||
return postRepository.save(postEntity);
|
||||
}
|
||||
|
||||
public PostEntity updatePost(long id, PostUpdateDto postUpdateDto) {
|
||||
PostEntity postEntity = getPostById(id);
|
||||
postEntity.setContent(postUpdateDto.getContent());
|
||||
postEntity.setModifiedAt(Clock.systemUTC().millis());
|
||||
return postRepository.save(postEntity);
|
||||
}
|
||||
}
|
||||
@@ -1,89 +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 Optional<UserEntity> getById(long id) {
|
||||
return userRepository.findByIdAndStatus(id, UserStatus.ACTIVE);
|
||||
}
|
||||
|
||||
public UserEntity getByEmail(String email) {
|
||||
return userRepository.findByEmailAndStatus(email, UserStatus.ACTIVE)
|
||||
.orElseThrow(() -> new ResourceNotFoundException("Users", email));
|
||||
}
|
||||
|
||||
public UserEntity getByIdOrElseThrow(long id) {
|
||||
return userRepository.findByIdAndStatus(id, UserStatus.ACTIVE)
|
||||
.orElseThrow(() -> new ResourceNotFoundException("Users", id));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public UserEntity createUser(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 updateUser(long id, UserUpdateDto userUpdateDto) {
|
||||
UserEntity userEntity = getByIdOrElseThrow(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.model.dto.UserResponse;
|
||||
import com.example.demo.repository.UserEntity;
|
||||
import com.example.demo.service.UserService;
|
||||
import com.example.demo.user.controller.port.UserService;
|
||||
import com.example.demo.user.controller.response.UserResponse;
|
||||
import com.example.demo.user.domain.User;
|
||||
import com.example.demo.user.domain.UserCreate;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.Builder;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -16,18 +17,18 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
@Tag(name = "유저(users)")
|
||||
@RestController
|
||||
@RequestMapping("/api/users")
|
||||
@Builder
|
||||
@RequiredArgsConstructor
|
||||
public class UserCreateController {
|
||||
|
||||
private final UserController userController;
|
||||
private final UserService userService;
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<UserResponse> createUser(@RequestBody UserCreateDto userCreateDto) {
|
||||
UserEntity userEntity = userService.createUser(userCreateDto);
|
||||
public ResponseEntity<UserResponse> create(@RequestBody UserCreate userCreate) {
|
||||
User user = userService.create(userCreate);
|
||||
return ResponseEntity
|
||||
.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 lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class UserCreateDto {
|
||||
public class UserCreate {
|
||||
|
||||
private final String email;
|
||||
private final String nickname;
|
||||
private final String address;
|
||||
|
||||
@Builder
|
||||
public UserCreateDto(
|
||||
public UserCreate(
|
||||
@JsonProperty("email") String email,
|
||||
@JsonProperty("nickname") String nickname,
|
||||
@JsonProperty("address") String address) {
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.demo.model;
|
||||
package com.example.demo.user.domain;
|
||||
|
||||
public enum UserStatus {
|
||||
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 lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class UserUpdateDto {
|
||||
public class UserUpdate {
|
||||
|
||||
private final String nickname;
|
||||
private final String address;
|
||||
|
||||
@Builder
|
||||
public UserUpdateDto(
|
||||
public UserUpdate(
|
||||
@JsonProperty("nickname") String nickname,
|
||||
@JsonProperty("address") String address) {
|
||||
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 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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
30
src/test/java/com/example/demo/medium/HealthCheckTest.java
Normal file
30
src/test/java/com/example/demo/medium/HealthCheckTest.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package com.example.demo.medium;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
@AutoConfigureTestDatabase
|
||||
public class HealthCheckTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Test
|
||||
void 헬스_체크_응답이_200으로_내려온다() throws Exception {
|
||||
// given
|
||||
// when
|
||||
// then
|
||||
mockMvc.perform(get("/health_check.html"))
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.example.demo.medium;
|
||||
|
||||
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.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import com.example.demo.post.domain.PostUpdate;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.jdbc.Sql;
|
||||
import org.springframework.test.context.jdbc.Sql.ExecutionPhase;
|
||||
import org.springframework.test.context.jdbc.SqlGroup;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
@AutoConfigureTestDatabase
|
||||
@SqlGroup({
|
||||
@Sql(value = "/sql/post-controller-test-data.sql", executionPhase = ExecutionPhase.BEFORE_TEST_METHOD),
|
||||
@Sql(value = "/sql/delete-all-data.sql", executionPhase = ExecutionPhase.AFTER_TEST_METHOD)
|
||||
})
|
||||
public class PostControllerTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@Test
|
||||
void 사용자는_게시물을_단건_조회_할_수_있다() throws Exception {
|
||||
// given
|
||||
// when
|
||||
// then
|
||||
mockMvc.perform(get("/api/posts/1"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.id").isNumber())
|
||||
.andExpect(jsonPath("$.content").value("helloworld"))
|
||||
.andExpect(jsonPath("$.writer.id").isNumber())
|
||||
.andExpect(jsonPath("$.writer.email").value("kok202@naver.com"))
|
||||
.andExpect(jsonPath("$.writer.nickname").value("kok202"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void 사용자가_존재하지_않는_게시물을_조회할_경우_에러가_난다() throws Exception {
|
||||
// given
|
||||
// when
|
||||
// then
|
||||
mockMvc.perform(get("/api/posts/123456789"))
|
||||
.andExpect(status().isNotFound())
|
||||
.andExpect(content().string("Posts에서 ID 123456789를 찾을 수 없습니다."));
|
||||
}
|
||||
|
||||
@Test
|
||||
void 사용자는_게시물을_수정할_수_있다() throws Exception {
|
||||
// given
|
||||
PostUpdate postUpdate = PostUpdate.builder()
|
||||
.content("foobar")
|
||||
.build();
|
||||
|
||||
// when
|
||||
// then
|
||||
mockMvc.perform(
|
||||
put("/api/posts/1")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(postUpdate)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.id").isNumber())
|
||||
.andExpect(jsonPath("$.content").value("foobar"))
|
||||
.andExpect(jsonPath("$.writer.id").isNumber())
|
||||
.andExpect(jsonPath("$.writer.email").value("kok202@naver.com"))
|
||||
.andExpect(jsonPath("$.writer.nickname").value("kok202"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.example.demo.medium;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import com.example.demo.post.domain.PostCreate;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.jdbc.Sql;
|
||||
import org.springframework.test.context.jdbc.Sql.ExecutionPhase;
|
||||
import org.springframework.test.context.jdbc.SqlGroup;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
@AutoConfigureTestDatabase
|
||||
@SqlGroup({
|
||||
@Sql(value = "/sql/post-create-controller-test-data.sql", executionPhase = ExecutionPhase.BEFORE_TEST_METHOD),
|
||||
@Sql(value = "/sql/delete-all-data.sql", executionPhase = ExecutionPhase.AFTER_TEST_METHOD)
|
||||
})
|
||||
public class PostCreateControllerTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@Test
|
||||
void 사용자는_게시물을_작성할_수_있다() throws Exception {
|
||||
// given
|
||||
PostCreate postCreate = PostCreate.builder()
|
||||
.writerId(1)
|
||||
.content("helloworld")
|
||||
.build();
|
||||
|
||||
// when
|
||||
// then
|
||||
mockMvc.perform(
|
||||
post("/api/posts")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(postCreate)))
|
||||
.andExpect(status().isCreated())
|
||||
.andExpect(jsonPath("$.id").isNumber())
|
||||
.andExpect(jsonPath("$.content").value("helloworld"))
|
||||
.andExpect(jsonPath("$.writer.id").isNumber())
|
||||
.andExpect(jsonPath("$.writer.email").value("kok202@naver.com"))
|
||||
.andExpect(jsonPath("$.writer.nickname").value("kok202"));
|
||||
}
|
||||
}
|
||||
72
src/test/java/com/example/demo/medium/PostServiceTest.java
Normal file
72
src/test/java/com/example/demo/medium/PostServiceTest.java
Normal file
@@ -0,0 +1,72 @@
|
||||
package com.example.demo.medium;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
|
||||
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.PostServiceImpl;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.jdbc.Sql;
|
||||
import org.springframework.test.context.jdbc.Sql.ExecutionPhase;
|
||||
import org.springframework.test.context.jdbc.SqlGroup;
|
||||
|
||||
@SpringBootTest
|
||||
@TestPropertySource("classpath:test-application.properties")
|
||||
@SqlGroup({
|
||||
@Sql(value = "/sql/post-service-test-data.sql", executionPhase = ExecutionPhase.BEFORE_TEST_METHOD),
|
||||
@Sql(value = "/sql/delete-all-data.sql", executionPhase = ExecutionPhase.AFTER_TEST_METHOD)
|
||||
})
|
||||
public class PostServiceTest {
|
||||
|
||||
@Autowired
|
||||
private PostServiceImpl postService;
|
||||
|
||||
@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()).isGreaterThan(0);
|
||||
}
|
||||
|
||||
@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()).isGreaterThan(0);
|
||||
}
|
||||
|
||||
}
|
||||
128
src/test/java/com/example/demo/medium/UserControllerTest.java
Normal file
128
src/test/java/com/example/demo/medium/UserControllerTest.java
Normal file
@@ -0,0 +1,128 @@
|
||||
package com.example.demo.medium;
|
||||
|
||||
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.put;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import com.example.demo.user.domain.UserStatus;
|
||||
import com.example.demo.user.domain.UserUpdate;
|
||||
import com.example.demo.user.infrastructure.UserEntity;
|
||||
import com.example.demo.user.infrastructure.UserJpaRepository;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.jdbc.Sql;
|
||||
import org.springframework.test.context.jdbc.Sql.ExecutionPhase;
|
||||
import org.springframework.test.context.jdbc.SqlGroup;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
@AutoConfigureTestDatabase
|
||||
@SqlGroup({
|
||||
@Sql(value = "/sql/user-controller-test-data.sql", executionPhase = ExecutionPhase.BEFORE_TEST_METHOD),
|
||||
@Sql(value = "/sql/delete-all-data.sql", executionPhase = ExecutionPhase.AFTER_TEST_METHOD)
|
||||
})
|
||||
public class UserControllerTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
@Autowired
|
||||
private UserJpaRepository userJpaRepository;
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@Test
|
||||
void 사용자는_특정_유저의_정보를_개인정보는_소거된채_전달_받을_수_있다() throws Exception {
|
||||
// given
|
||||
// when
|
||||
// then
|
||||
mockMvc.perform(get("/api/users/1"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.id").value(1))
|
||||
.andExpect(jsonPath("$.email").value("kok202@naver.com"))
|
||||
.andExpect(jsonPath("$.nickname").value("kok202"))
|
||||
.andExpect(jsonPath("$.address").doesNotExist())
|
||||
.andExpect(jsonPath("$.status").value("ACTIVE"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void 사용자는_존재하지_않는_유저의_아이디로_api_호출할_경우_404_응답을_받는다() throws Exception {
|
||||
// given
|
||||
// when
|
||||
// then
|
||||
mockMvc.perform(get("/api/users/123456789"))
|
||||
.andExpect(status().isNotFound())
|
||||
.andExpect(content().string("Users에서 ID 123456789를 찾을 수 없습니다."));
|
||||
}
|
||||
|
||||
@Test
|
||||
void 사용자는_인증_코드로_계정을_활성화_시킬_수_있다() throws Exception {
|
||||
// given
|
||||
// when
|
||||
// then
|
||||
mockMvc.perform(
|
||||
get("/api/users/2/verify")
|
||||
.queryParam("certificationCode", "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab"))
|
||||
.andExpect(status().isFound());
|
||||
UserEntity userEntity = userJpaRepository.findById(1L).get();
|
||||
assertThat(userEntity.getStatus()).isEqualTo(UserStatus.ACTIVE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void 사용자는_인증_코드가_일치하지_않을_경우_권한_없음_에러를_내려준다() throws Exception {
|
||||
// given
|
||||
// when
|
||||
// then
|
||||
mockMvc.perform(
|
||||
get("/api/users/2/verify")
|
||||
.queryParam("certificationCode", "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaac"))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
void 사용자는_내_정보를_불러올_때_개인정보인_주소도_갖고_올_수_있다() throws Exception {
|
||||
// given
|
||||
// when
|
||||
// then
|
||||
mockMvc.perform(
|
||||
get("/api/users/me")
|
||||
.header("EMAIL", "kok202@naver.com"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.id").value(1))
|
||||
.andExpect(jsonPath("$.email").value("kok202@naver.com"))
|
||||
.andExpect(jsonPath("$.nickname").value("kok202"))
|
||||
.andExpect(jsonPath("$.address").value("Seoul"))
|
||||
.andExpect(jsonPath("$.status").value("ACTIVE"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void 사용자는_내_정보를_수정할_수_있다() throws Exception {
|
||||
// given
|
||||
UserUpdate userUpdate = UserUpdate.builder()
|
||||
.nickname("kok202-n")
|
||||
.address("Pangyo")
|
||||
.build();
|
||||
|
||||
// when
|
||||
// then
|
||||
mockMvc.perform(
|
||||
put("/api/users/me")
|
||||
.header("EMAIL", "kok202@naver.com")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(userUpdate)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.id").value(1))
|
||||
.andExpect(jsonPath("$.email").value("kok202@naver.com"))
|
||||
.andExpect(jsonPath("$.nickname").value("kok202-n"))
|
||||
.andExpect(jsonPath("$.address").value("Pangyo"))
|
||||
.andExpect(jsonPath("$.status").value("ACTIVE"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.example.demo.medium;
|
||||
|
||||
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 static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import com.example.demo.user.domain.UserCreate;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.BDDMockito;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mail.SimpleMailMessage;
|
||||
import org.springframework.mail.javamail.JavaMailSender;
|
||||
import org.springframework.test.context.jdbc.Sql;
|
||||
import org.springframework.test.context.jdbc.Sql.ExecutionPhase;
|
||||
import org.springframework.test.context.jdbc.SqlGroup;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
@AutoConfigureTestDatabase
|
||||
@SqlGroup({
|
||||
@Sql(value = "/sql/delete-all-data.sql", executionPhase = ExecutionPhase.AFTER_TEST_METHOD)
|
||||
})
|
||||
public class UserCreateControllerTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
@MockBean
|
||||
private JavaMailSender mailSender;
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@Test
|
||||
void 사용자는_회원_가입을_할_수있고_회원가입된_사용자는_PENDING_상태이다() throws Exception {
|
||||
// given
|
||||
UserCreate userCreate = UserCreate.builder()
|
||||
.email("kok202@kakao.com")
|
||||
.nickname("kok202")
|
||||
.address("Pangyo")
|
||||
.build();
|
||||
BDDMockito.doNothing().when(mailSender).send(any(SimpleMailMessage.class));
|
||||
|
||||
// when
|
||||
// then
|
||||
mockMvc.perform(
|
||||
post("/api/users")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(userCreate)))
|
||||
.andExpect(status().isCreated())
|
||||
.andExpect(jsonPath("$.id").isNumber())
|
||||
.andExpect(jsonPath("$.email").value("kok202@kakao.com"))
|
||||
.andExpect(jsonPath("$.nickname").value("kok202"))
|
||||
.andExpect(jsonPath("$.status").value("PENDING"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.example.demo.medium;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
|
||||
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 org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.jdbc.Sql;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@DataJpaTest(showSql = true)
|
||||
@TestPropertySource("classpath:test-application.properties")
|
||||
@Sql("/sql/user-repository-test-data.sql")
|
||||
public class UserJpaRepositoryTest {
|
||||
|
||||
@Autowired
|
||||
private UserJpaRepository userJpaRepository;
|
||||
|
||||
@Test
|
||||
void findByIdAndStatus_로_유저_데이터를_찾아올_수_있다() {
|
||||
// given
|
||||
// when
|
||||
Optional<UserEntity> result = userJpaRepository.findByIdAndStatus(1, UserStatus.ACTIVE);
|
||||
|
||||
// then
|
||||
assertThat(result.isPresent()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void findByIdAndStatus_는_데이터가_없으면_Optional_empty_를_내려준다() {
|
||||
// given
|
||||
// when
|
||||
Optional<UserEntity> result = userJpaRepository.findByIdAndStatus(1, UserStatus.PENDING);
|
||||
|
||||
// then
|
||||
assertThat(result.isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void findByEmailAndStatus_로_유저_데이터를_찾아올_수_있다() {
|
||||
// given
|
||||
// when
|
||||
Optional<UserEntity> result = userJpaRepository.findByEmailAndStatus("kok202@naver.com", UserStatus.ACTIVE);
|
||||
|
||||
// then
|
||||
assertThat(result.isPresent()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void findByEmailAndStatus_는_데이터가_없으면_Optional_empty_를_내려준다() {
|
||||
// given
|
||||
// when
|
||||
Optional<UserEntity> result = userJpaRepository.findByEmailAndStatus("kok202@naver.com", UserStatus.PENDING);
|
||||
|
||||
// then
|
||||
assertThat(result.isEmpty()).isTrue();
|
||||
}
|
||||
}
|
||||
153
src/test/java/com/example/demo/medium/UserServiceTest.java
Normal file
153
src/test/java/com/example/demo/medium/UserServiceTest.java
Normal file
@@ -0,0 +1,153 @@
|
||||
package com.example.demo.medium;
|
||||
|
||||
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.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.UserServiceImpl;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.BDDMockito;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.mail.SimpleMailMessage;
|
||||
import org.springframework.mail.javamail.JavaMailSender;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.jdbc.Sql;
|
||||
import org.springframework.test.context.jdbc.Sql.ExecutionPhase;
|
||||
import org.springframework.test.context.jdbc.SqlGroup;
|
||||
|
||||
@SpringBootTest
|
||||
@TestPropertySource("classpath:test-application.properties")
|
||||
@SqlGroup({
|
||||
@Sql(value = "/sql/user-service-test-data.sql", executionPhase = ExecutionPhase.BEFORE_TEST_METHOD),
|
||||
@Sql(value = "/sql/delete-all-data.sql", executionPhase = ExecutionPhase.AFTER_TEST_METHOD)
|
||||
})
|
||||
public class UserServiceTest {
|
||||
|
||||
@Autowired
|
||||
private UserServiceImpl userService;
|
||||
@MockBean
|
||||
private JavaMailSender mailSender;
|
||||
|
||||
@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();
|
||||
BDDMockito.doNothing().when(mailSender).send(any(SimpleMailMessage.class));
|
||||
|
||||
// when
|
||||
User result = userService.create(userCreate);
|
||||
|
||||
// then
|
||||
assertThat(result.getId()).isNotNull();
|
||||
assertThat(result.getStatus()).isEqualTo(UserStatus.PENDING);
|
||||
// assertThat(result.getCertificationCode()).isEqualTo("T.T"); // FIXME
|
||||
}
|
||||
|
||||
@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()).isGreaterThan(0L);
|
||||
// assertThat(result.getLastLoginAt()).isEqualTo("T.T"); // FIXME
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
3
src/test/resources/sql/delete-all-data.sql
Normal file
3
src/test/resources/sql/delete-all-data.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
delete from `posts` where 1;
|
||||
delete from `users` where 1;
|
||||
5
src/test/resources/sql/post-controller-test-data.sql
Normal file
5
src/test/resources/sql/post-controller-test-data.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`)
|
||||
values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0);
|
||||
insert into `posts` (`id`, `content`, `created_at`, `modified_at`, `user_id`)
|
||||
values (1, 'helloworld', 1678530673958, 0, 1);
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`)
|
||||
values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0);
|
||||
7
src/test/resources/sql/post-service-test-data.sql
Normal file
7
src/test/resources/sql/post-service-test-data.sql
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`)
|
||||
values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0);
|
||||
insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`)
|
||||
values (2, 'kok303@naver.com', 'kok303', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0);
|
||||
insert into `posts` (`id`, `content`, `created_at`, `modified_at`, `user_id`)
|
||||
values (1, 'helloworld', 1678530673958, 0, 1);
|
||||
5
src/test/resources/sql/user-controller-test-data.sql
Normal file
5
src/test/resources/sql/user-controller-test-data.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`)
|
||||
values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0);
|
||||
insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`)
|
||||
values (2, 'kok303@naver.com', 'kok303', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0);
|
||||
3
src/test/resources/sql/user-repository-test-data.sql
Normal file
3
src/test/resources/sql/user-repository-test-data.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`)
|
||||
values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0);
|
||||
5
src/test/resources/sql/user-service-test-data.sql
Normal file
5
src/test/resources/sql/user-service-test-data.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`)
|
||||
values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0);
|
||||
insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`)
|
||||
values (2, 'kok303@naver.com', 'kok303', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0);
|
||||
9
src/test/resources/test-application.properties
Normal file
9
src/test/resources/test-application.properties
Normal file
@@ -0,0 +1,9 @@
|
||||
spring.datasource.url=jdbc:h2:mem:testdb;MODE=MySQL;DB_CLOSE_DELAY=-1
|
||||
spring.datasource.driverClassName=org.h2.Driver
|
||||
spring.datasource.username=sa
|
||||
spring.datasource.password=
|
||||
spring.h2.console.enabled=true
|
||||
|
||||
spring.jpa.hibernate.dialect=org.hibernate.dialect.MariaDBDialect
|
||||
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
|
||||
spring.jpa.hibernate.ddl-auto=create-drop
|
||||
Reference in New Issue
Block a user