diff --git a/build.gradle b/build.gradle index e5ec1a5..3b55e26 100644 --- a/build.gradle +++ b/build.gradle @@ -27,6 +27,7 @@ dependencies { compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' annotationProcessor 'org.projectlombok:lombok' + implementation 'org.springframework.boot:spring-boot-starter-validation' testImplementation 'org.springframework.boot:spring-boot-starter-test' } diff --git a/readme.md b/readme.md index 0e8875a..640e832 100644 --- a/readme.md +++ b/readme.md @@ -28,18 +28,18 @@ #### 패키지 구조 ```text ├── controller -│   └── UserController.java +│   └── MemberController.java ├── domain -│   ├── User.java -│   ├── UserLevel.java -│   └── UserType.java +│   ├── Member.java +│   ├── MemberLevel.java +│   └── MemberType.java ├── repository -│   └── UserRepository.java +│   └── MemberRepository.java └── service - └── UserService.java + └── MemberService.java ``` -* 모든 도메인 패키지 구조는 다음을 따릅니다. (예시 : `user` 도메인) +* 모든 도메인 패키지 구조는 다음을 따릅니다. (예시 : `Member` 도메인) * 각 패키지 내부의 클래스들은 예시일 뿐 얼마든지 클래스를 추가로 생성하셔도 됩니다. ### 유저 도메인을 완성해봅시다. @@ -49,8 +49,8 @@ | username | 사용자 아이디 | 사용자 로그인 아이디 | | password | 사용자 비밀번호 | 사용자 비밀번호 | | nickname | 사용자 닉네임 | 사용자 닉네임 | -| userLevel | 사용자 등급 | 사용자 등급 | -| type | 사용자 유형 | 사용자 유형으로 ADMIN, USER가 존재 | +| MemberLevel | 사용자 등급 | 사용자 등급 | +| type | 사용자 유형 | 사용자 유형으로 ADMIN, Member가 존재 | | createdAt | 생성 일시 | 사용자 최초 생성 일시 | | lastModifiedAt | 최종 수정 일시 | 사용자 최종 수정 일시 | * 사용자는 `회원가입`이 가능합니다. @@ -62,7 +62,7 @@ * BRONZE, SILVER, GOLD가 존재하며 추후 주문 시 결제 금액 할인이 가능합니다. * 5번 구매를 하면 SILVER, 10번 구매를 하면 GOLD로 등급업이 됩니다. * 사용자 별 `타입(type)`이 존재합니다. - * USER : 일반유저로 상품을 구매는 가능하지만 추가할 수 없습니다. + * Member : 일반유저로 상품을 구매는 가능하지만 추가할 수 없습니다. * ADMIN : 관리자로 상품을 구매와 추가 모두 가능합니다.
@@ -93,7 +93,7 @@ | 변수명 | 필드명 | 설명 | |----------------|----------|------------| | id | 주문 아이디 | 주문 엔티티 식별자 | -| userId | 유저 아이디 | 유저 엔티티 식별자 | +| MemberId | 유저 아이디 | 유저 엔티티 식별자 | | orderProducts | 주문 상품 정보 | 주문의 상품의 정보 | | price | 총 주문 가격 | 총 주문 가격 | | orderStatus | 주문 상태 | 주문 상태 | diff --git a/src/main/java/com/swger/tddstudy/member/controller/MemberController.java b/src/main/java/com/swger/tddstudy/member/controller/MemberController.java new file mode 100644 index 0000000..ff02db2 --- /dev/null +++ b/src/main/java/com/swger/tddstudy/member/controller/MemberController.java @@ -0,0 +1,44 @@ +package com.swger.tddstudy.member.controller; + +import com.swger.tddstudy.member.domain.Member; +import com.swger.tddstudy.member.domain.DTO.MemberDTO; +import com.swger.tddstudy.member.domain.DTO.MemberSignInDTO; +import com.swger.tddstudy.member.repository.MemberRepository; +import com.swger.tddstudy.member.service.MemberService; +import javax.servlet.http.HttpSession; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequiredArgsConstructor +public class MemberController { + + private final MemberService memberService; + + @PostMapping("/signUp") + public String signUp(@Validated @RequestBody MemberDTO memberDTO, BindingResult bindingResult) + throws Exception { + if (bindingResult.hasErrors()) { + throw new BindException(bindingResult); + } + memberService.SignUp(memberDTO); + return "signUpOK"; + } + + @PostMapping("/logIn") + public String logIn(@Validated @RequestBody MemberSignInDTO memberSignInDTO, + BindingResult bindingResult, HttpSession session) throws Exception { + if (bindingResult.hasErrors()) { + throw new BindException(bindingResult); + } + Member member = memberService.SignIn(memberSignInDTO); + session.setAttribute("id", member.getId()); + return "LogInOK"; + } + +} diff --git a/src/main/java/com/swger/tddstudy/member/domain/DTO/MemberDTO.java b/src/main/java/com/swger/tddstudy/member/domain/DTO/MemberDTO.java new file mode 100644 index 0000000..85370e0 --- /dev/null +++ b/src/main/java/com/swger/tddstudy/member/domain/DTO/MemberDTO.java @@ -0,0 +1,25 @@ +package com.swger.tddstudy.member.domain.DTO; + +import lombok.Getter; + +import javax.validation.constraints.NotBlank; + +@Getter +public class MemberDTO { + @NotBlank + private String username; + @NotBlank + private String password; + @NotBlank + private String nickname; + @NotBlank + private String rePassword; + + public MemberDTO(String username, String password, String nickname, String rePassword) { + this.username = username; + this.password = password; + this.nickname = nickname; + this.rePassword = rePassword; + } + public MemberDTO(){} +} diff --git a/src/main/java/com/swger/tddstudy/member/domain/DTO/MemberSignInDTO.java b/src/main/java/com/swger/tddstudy/member/domain/DTO/MemberSignInDTO.java new file mode 100644 index 0000000..2887370 --- /dev/null +++ b/src/main/java/com/swger/tddstudy/member/domain/DTO/MemberSignInDTO.java @@ -0,0 +1,20 @@ +package com.swger.tddstudy.member.domain.DTO; + +import lombok.Getter; + +import javax.validation.constraints.NotBlank; + +@Getter +public class MemberSignInDTO { + + @NotBlank + private String username; + @NotBlank + private String password; + + public MemberSignInDTO(String username, String password) { + this.username = username; + this.password = password; + } + public MemberSignInDTO(){} +} diff --git a/src/main/java/com/swger/tddstudy/member/domain/Member.java b/src/main/java/com/swger/tddstudy/member/domain/Member.java new file mode 100644 index 0000000..3555636 --- /dev/null +++ b/src/main/java/com/swger/tddstudy/member/domain/Member.java @@ -0,0 +1,61 @@ +package com.swger.tddstudy.member.domain; + +import com.swger.tddstudy.member.domain.DTO.MemberDTO; +import com.swger.tddstudy.util.BaseEntity; + +import javax.persistence.*; +import javax.validation.constraints.NotBlank; + +import lombok.Getter; + +@Getter +@Entity +public class Member extends BaseEntity { + + @Id @GeneratedValue + private Long id; + + @NotBlank + private String username; + + @NotBlank + private String password; + + @NotBlank + private String nickname; + + @Enumerated(EnumType.STRING) + private MemberLevel memberLevel; + + @Enumerated(EnumType.STRING) + private MemberType memberType; + + public Member(String username, String password, String nickname) { + this.username = username; + this.password = password; + this.nickname = nickname; + this.memberLevel = MemberLevel.BRONZE; + this.memberType = MemberType.Member; + } + public Member(){} + + public Member(MemberDTO memberDTO){ + this.username = memberDTO.getUsername(); + this.password = memberDTO.getPassword(); + this.nickname = memberDTO.getNickname(); + this.memberLevel = MemberLevel.BRONZE; + this.memberType = MemberType.Member; + } + public void AdminMember(){ + this.memberType = MemberType.ADMIN; + } + public void LevelUp() { + if (this.getMemberLevel().equals(MemberLevel.SILVER)) { + this.memberLevel = MemberLevel.GOLD; + } + if (this.getMemberLevel().equals(MemberLevel.BRONZE)) { + this.memberLevel = MemberLevel.SILVER; + } + } + +} diff --git a/src/main/java/com/swger/tddstudy/user/domain/UserLevel.java b/src/main/java/com/swger/tddstudy/member/domain/MemberLevel.java similarity index 70% rename from src/main/java/com/swger/tddstudy/user/domain/UserLevel.java rename to src/main/java/com/swger/tddstudy/member/domain/MemberLevel.java index 4f9e926..9a884b6 100644 --- a/src/main/java/com/swger/tddstudy/user/domain/UserLevel.java +++ b/src/main/java/com/swger/tddstudy/member/domain/MemberLevel.java @@ -1,9 +1,9 @@ -package com.swger.tddstudy.user.domain; +package com.swger.tddstudy.member.domain; import lombok.RequiredArgsConstructor; @RequiredArgsConstructor -public enum UserLevel { +public enum MemberLevel { BRONZE("브론즈"), SILVER("실버"), GOLD("골드"); diff --git a/src/main/java/com/swger/tddstudy/member/domain/MemberType.java b/src/main/java/com/swger/tddstudy/member/domain/MemberType.java new file mode 100644 index 0000000..9e86662 --- /dev/null +++ b/src/main/java/com/swger/tddstudy/member/domain/MemberType.java @@ -0,0 +1,12 @@ +package com.swger.tddstudy.member.domain; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum MemberType { + + Member("일반회원"), ADMIN("관리자"); + + private final String text; + +} diff --git a/src/main/java/com/swger/tddstudy/member/repository/MemberRepository.java b/src/main/java/com/swger/tddstudy/member/repository/MemberRepository.java new file mode 100644 index 0000000..9d5d52e --- /dev/null +++ b/src/main/java/com/swger/tddstudy/member/repository/MemberRepository.java @@ -0,0 +1,14 @@ +package com.swger.tddstudy.member.repository; + +import com.swger.tddstudy.member.domain.Member; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; +import java.util.Optional; + +public interface MemberRepository extends JpaRepository { + Optional findByUsername(String username); + + @Override + S save(S entity); +} diff --git a/src/main/java/com/swger/tddstudy/member/service/MemberService.java b/src/main/java/com/swger/tddstudy/member/service/MemberService.java new file mode 100644 index 0000000..8864ed5 --- /dev/null +++ b/src/main/java/com/swger/tddstudy/member/service/MemberService.java @@ -0,0 +1,48 @@ +package com.swger.tddstudy.member.service; + +import com.swger.tddstudy.member.domain.Member; +import com.swger.tddstudy.member.domain.DTO.MemberDTO; +import com.swger.tddstudy.member.domain.DTO.MemberSignInDTO; +import com.swger.tddstudy.member.domain.MemberLevel; +import com.swger.tddstudy.member.domain.MemberType; +import com.swger.tddstudy.member.repository.MemberRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class MemberService { + private final MemberRepository memberRepository; + public Member join(Member member){ + memberRepository.save(member); + return member; + } + public Member SignUp(MemberDTO member){ + if(!member.getPassword().equals(member.getRePassword())){ + throw new IllegalArgumentException("RePassword Mismatch"); + } + Member signUpMember = new Member(member); + join(signUpMember); + return signUpMember; + } + public Member SignUpAdmin(MemberDTO member){ + if(!member.getPassword().equals(member.getRePassword())){ + throw new IllegalArgumentException("RePassword Mismatch"); + } + Member signUpMember = new Member(member); + signUpMember.AdminMember(); + join(signUpMember); + return signUpMember; + } + public Member SignIn(MemberSignInDTO member){ + Member signInMember = memberRepository.findByUsername(member.getUsername()).orElseThrow(() -> new IllegalArgumentException("Username Mismatch")); + if (!signInMember.getPassword().equals(member.getPassword())) { + throw new IllegalArgumentException("Password Mismatch"); + } + return signInMember; + } + +} diff --git a/src/main/java/com/swger/tddstudy/order/domain/Order.java b/src/main/java/com/swger/tddstudy/order/domain/Order.java index 3267f59..bc978f1 100644 --- a/src/main/java/com/swger/tddstudy/order/domain/Order.java +++ b/src/main/java/com/swger/tddstudy/order/domain/Order.java @@ -2,7 +2,7 @@ import com.swger.tddstudy.orderProduct.domain.OrderProduct; import com.swger.tddstudy.util.BaseEntity; -import com.swger.tddstudy.user.domain.User; +import com.swger.tddstudy.member.domain.Member; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Entity; @@ -26,13 +26,13 @@ public class Order extends BaseEntity { private Long id; @ManyToOne - private User user; + private Member Member; @OneToMany(mappedBy = "order", cascade = CascadeType.ALL) private List orderProducts; private int price; - @Enum태erated(EnumType.STRING) + @Enumerated(EnumType.STRING) private OrderStatus orderStatus; } diff --git a/src/main/java/com/swger/tddstudy/product/controller/ProductController.java b/src/main/java/com/swger/tddstudy/product/controller/ProductController.java new file mode 100644 index 0000000..acaa73f --- /dev/null +++ b/src/main/java/com/swger/tddstudy/product/controller/ProductController.java @@ -0,0 +1,43 @@ +package com.swger.tddstudy.product.controller; + +import com.swger.tddstudy.member.domain.MemberType; +import com.swger.tddstudy.member.repository.MemberRepository; +import com.swger.tddstudy.member.service.MemberService; +import com.swger.tddstudy.product.domain.DTO.ProductRegisterDTO; +import com.swger.tddstudy.product.service.ProductService; +import javax.naming.AuthenticationException; +import javax.servlet.http.HttpSession; +import lombok.RequiredArgsConstructor; +import org.hibernate.engine.spi.ManagedEntity; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +public class ProductController { + + private final ProductService productService; + private final MemberRepository memberRepository; + + @PostMapping("/productRegister") + public String productRegister(@Validated @RequestBody ProductRegisterDTO DTO, BindingResult br, + HttpSession httpSession) throws BindException, AuthenticationException { + if (br.hasErrors()) throw new BindException(br); + productService.register(DTO); + + if (httpSession.getAttribute("id") == null) { + throw new AuthenticationException("You must SignIn"); + } + + if(!memberRepository.findById((Long) httpSession.getAttribute("id")) + .get().getMemberType().equals(MemberType.ADMIN)){ + throw new AuthenticationException("You are not Admin"); + } + return "Register OK"; + } +} diff --git a/src/main/java/com/swger/tddstudy/product/controller/ProductControllerAdvice.java b/src/main/java/com/swger/tddstudy/product/controller/ProductControllerAdvice.java new file mode 100644 index 0000000..4820d06 --- /dev/null +++ b/src/main/java/com/swger/tddstudy/product/controller/ProductControllerAdvice.java @@ -0,0 +1,26 @@ +package com.swger.tddstudy.product.controller; + +import javax.naming.AuthenticationException; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.BindException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +@ControllerAdvice +public class ProductControllerAdvice { + + @ExceptionHandler + public ResponseEntity bindException(BindException e) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .contentType(MediaType.APPLICATION_JSON) + .body(e.getBindingResult().getAllErrors().get(0).getDefaultMessage()); + } + @ExceptionHandler + public ResponseEntity authenticationException(AuthenticationException e) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .contentType(MediaType.APPLICATION_JSON) + .body(e.getMessage()); + } +} diff --git a/src/main/java/com/swger/tddstudy/product/domain/DTO/ProductRegisterDTO.java b/src/main/java/com/swger/tddstudy/product/domain/DTO/ProductRegisterDTO.java new file mode 100644 index 0000000..9a53ce1 --- /dev/null +++ b/src/main/java/com/swger/tddstudy/product/domain/DTO/ProductRegisterDTO.java @@ -0,0 +1,26 @@ +package com.swger.tddstudy.product.domain.DTO; + +import lombok.Getter; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; + +@Getter +public class ProductRegisterDTO { + @NotBlank + private String name; + + @Min(1000) + private int price; + + @Min(1) + private int amount; + + public ProductRegisterDTO(String name, int price, int amount) { + this.name = name; + this.price = price; + this.amount = amount; + } + public ProductRegisterDTO(){} + +} diff --git a/src/main/java/com/swger/tddstudy/product/domain/Product.java b/src/main/java/com/swger/tddstudy/product/domain/Product.java index e71ebd9..3729658 100644 --- a/src/main/java/com/swger/tddstudy/product/domain/Product.java +++ b/src/main/java/com/swger/tddstudy/product/domain/Product.java @@ -1,10 +1,11 @@ package com.swger.tddstudy.product.domain; import com.swger.tddstudy.util.BaseEntity; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.Id; + +import javax.persistence.*; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; + import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; @@ -15,14 +16,56 @@ public class Product extends BaseEntity { @Id + @GeneratedValue private Long id; + @NotBlank private String name; + @Min(1000) private int price; + @Min(1) private int amount; @Enumerated(EnumType.STRING) private SellingStatus sellingStatus; + + public Product(String name, int price, int amount) { + this.name = name; + this.price = price; + this.amount = amount; + this.sellingStatus = SellingStatus.SELLING; + } + public boolean sellProduct(int cnt){ + /* 사용자가 재고 이상으로 주문 */ + if (cnt > this.amount) { + return false; + } + /* 사용자가 재고에 맞게 주문 */ + this.amount -= cnt; + return true; + } + public void sellStop(){ + this.sellingStatus = SellingStatus.STOP_SELLING; + } + public void sellStart(){ + this.sellingStatus = SellingStatus.SELLING; + } + + public boolean sellingOrNo() { + /* 처음부터 재고 수량 = 0 */ + if (this.getSellingStatus() == SellingStatus.STOP_SELLING) { + return false; + } + /* 구매 가능 */ + if (this.getAmount() > 0 && this.getSellingStatus() == SellingStatus.SELLING) { + return true;} + else { + /* 재고수량이 처음으로 0이 되었을 때 */ + this.sellStop(); + return false; + } + } + } diff --git a/src/main/java/com/swger/tddstudy/product/repository/ProductRepository.java b/src/main/java/com/swger/tddstudy/product/repository/ProductRepository.java new file mode 100644 index 0000000..d1fd632 --- /dev/null +++ b/src/main/java/com/swger/tddstudy/product/repository/ProductRepository.java @@ -0,0 +1,8 @@ +package com.swger.tddstudy.product.repository; + +import com.swger.tddstudy.product.domain.Product; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ProductRepository extends JpaRepository { + +} diff --git a/src/main/java/com/swger/tddstudy/product/service/ProductService.java b/src/main/java/com/swger/tddstudy/product/service/ProductService.java new file mode 100644 index 0000000..e4c0938 --- /dev/null +++ b/src/main/java/com/swger/tddstudy/product/service/ProductService.java @@ -0,0 +1,24 @@ +package com.swger.tddstudy.product.service; + +import com.swger.tddstudy.product.domain.DTO.ProductRegisterDTO; +import com.swger.tddstudy.product.domain.Product; +import com.swger.tddstudy.product.domain.SellingStatus; +import com.swger.tddstudy.product.repository.ProductRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.swing.text.TableView; + +@Service +@RequiredArgsConstructor +public class ProductService { + + private final ProductRepository productRepository; + + public Product register(ProductRegisterDTO product) { + Product save = productRepository.save(new Product(product.getName() + , product.getPrice(), product.getAmount())); + return save; + } + +} diff --git a/src/main/java/com/swger/tddstudy/user/domain/User.java b/src/main/java/com/swger/tddstudy/user/domain/User.java deleted file mode 100644 index 8df4eaa..0000000 --- a/src/main/java/com/swger/tddstudy/user/domain/User.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.swger.tddstudy.user.domain; - -import com.swger.tddstudy.util.BaseEntity; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.Id; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class User extends BaseEntity { - - @Id - private Long id; - - private String username; - - private String password; - - private String nickname; - - @Enumerated(EnumType.STRING) - private UserLevel userLevel; - - @Enumerated(EnumType.STRING) - private UserType type; -} diff --git a/src/main/java/com/swger/tddstudy/user/domain/UserType.java b/src/main/java/com/swger/tddstudy/user/domain/UserType.java deleted file mode 100644 index 73912c7..0000000 --- a/src/main/java/com/swger/tddstudy/user/domain/UserType.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.swger.tddstudy.user.domain; - -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -public enum UserType { - - USER("일반회원"), ADMIN("관리자"); - - private final String text; - -} diff --git a/src/test/java/com/swger/tddstudy/member/MemberControllerTest.java b/src/test/java/com/swger/tddstudy/member/MemberControllerTest.java new file mode 100644 index 0000000..bf48280 --- /dev/null +++ b/src/test/java/com/swger/tddstudy/member/MemberControllerTest.java @@ -0,0 +1,108 @@ +package com.swger.tddstudy.member; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.swger.tddstudy.member.domain.DTO.MemberDTO; +import com.swger.tddstudy.member.domain.DTO.MemberSignInDTO; +import com.swger.tddstudy.member.domain.Member; +import com.swger.tddstudy.member.repository.MemberRepository; +import com.swger.tddstudy.member.service.MemberService; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.validation.BindException; + +import javax.transaction.Transactional; + + +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@Transactional +@AutoConfigureMockMvc +public class MemberControllerTest { + @Autowired + MemberRepository memberRepository; + @Autowired + MemberService memberService; + @Autowired + private MockMvc mockMvc; + @Autowired + private ObjectMapper om; + + @DisplayName("회원 가입 성공") + @Test + public void SignUpSuccess() throws Exception { + //given + MemberDTO signInMember= new MemberDTO("testUsername", + "testPassword", "testNickname", "testPassword"); + String content = om.writeValueAsString(signInMember); + //when + mockMvc.perform(post("/signUp") + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().string("signUpOK")) + .andDo(print()); + Optional getMember = memberRepository.findByUsername(signInMember.getUsername()); + //then + /* 아이디, 비밀번호 같은지 확인*/ + Assertions.assertThat(getMember.get().getUsername()).isEqualTo(signInMember.getUsername()); + Assertions.assertThat(getMember.get().getPassword()).isEqualTo(signInMember.getPassword()); + } + + @DisplayName("회원가입 실패 - Validation 실패") + @Test + public void SignUpFail() throws Exception { + MemberDTO signInMember= new MemberDTO("testUsername", + "testPassword", null, "testPassword"); + String content = om.writeValueAsString(signInMember); + mockMvc.perform(post("/signUp") + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(result -> assertTrue(result.getResolvedException() + .getClass().isAssignableFrom(BindException.class))) + .andDo(print()); + + } + @DisplayName("로그인 성공") + @Test + public void SignInSuccess() throws Exception { + memberService.join(new Member("testUsername", "testPassword", "testNickName")); + MemberSignInDTO signInMember= new MemberSignInDTO("testUsername","testPassword"); + String content = om.writeValueAsString(signInMember); + mockMvc.perform(post("/logIn") + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().string("LogInOK")) + .andDo(print()); + } + @DisplayName("로그인 실패 - Vaildation 실패") + @Test + public void SignInFail() throws Exception { + memberService.join(new Member("testUsername", "testPassword", "testNickName")); + MemberSignInDTO signInMember= new MemberSignInDTO(null,"testPassword"); + String content = om.writeValueAsString(signInMember); + mockMvc.perform(post("/logIn") + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(result -> assertTrue(result.getResolvedException().getClass().isAssignableFrom(BindException.class))) + .andDo(print()); + } + +} diff --git a/src/test/java/com/swger/tddstudy/member/MemberServiceTest.java b/src/test/java/com/swger/tddstudy/member/MemberServiceTest.java new file mode 100644 index 0000000..7d410c5 --- /dev/null +++ b/src/test/java/com/swger/tddstudy/member/MemberServiceTest.java @@ -0,0 +1,109 @@ +package com.swger.tddstudy.member; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.swger.tddstudy.member.domain.DTO.MemberDTO; +import com.swger.tddstudy.member.domain.DTO.MemberSignInDTO; +import com.swger.tddstudy.member.domain.Member; +import com.swger.tddstudy.member.domain.MemberLevel; +import com.swger.tddstudy.member.domain.MemberType; +import com.swger.tddstudy.member.repository.MemberRepository; +import com.swger.tddstudy.member.service.MemberService; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import javax.transaction.Transactional; + +@SpringBootTest +@Transactional +public class MemberServiceTest { + @Autowired + MemberService memberService; + @Autowired + MemberRepository memberRepository; + + @DisplayName("회원가입 성공") + @Test + public void SignUpSuccessInService(){ + //given + MemberDTO memberDTO = new MemberDTO("testUsername", + "testPassword", "testNickname", "testPassword"); + //when + Member member = memberService.SignUp(memberDTO); + Member memberInRepos = memberRepository.findById(member.getId()).get(); + //then + Assertions.assertThat(member).extracting( + "id", "username", "nickname", "memberLevel", "memberType") + .containsExactly(memberInRepos.getId(), + memberInRepos.getUsername(), + memberInRepos.getNickname(), + memberInRepos.getMemberLevel(), + memberInRepos.getMemberType()); + } + @DisplayName("Admin 타입으로 회원가입") + @Test + public void SignUpAdmin(){ + //given + MemberDTO signUpMember= new MemberDTO("testUsername", + "testPassword", "testNickname", "testPassword"); + //when + Member adminMember = memberService.SignUpAdmin(signUpMember); + //then + Assertions.assertThat(adminMember.getMemberType()).isEqualTo(MemberType.ADMIN); + } + @DisplayName("회원가입 실패-비밀번호 재확인") + @Test + public void SignUpFailRePassword(){ + //given + MemberDTO memberDTO = new MemberDTO("testUsername", + "testPassword", "testNickname", "test"); + //when + //then + Assertions.assertThatThrownBy(() -> memberService.SignUp(memberDTO)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("RePassword Mismatch"); + } + @DisplayName("로그인 성공") + @Test + public void SignInSuccessInService(){ + //given + Member member = memberService.join(new Member("testUsername", "testPassword", "testNickName")); + MemberSignInDTO signInMemberDTO= new MemberSignInDTO("testUsername","testPassword"); + //when + Member signInMember = memberService.SignIn(signInMemberDTO); + //then + Assertions.assertThat(member).extracting( + "id", "username", "nickname", "memberLevel", "memberType") + .containsExactly(signInMember.getId(), + signInMember.getUsername(), + signInMember.getNickname(), + signInMember.getMemberLevel(), + signInMember.getMemberType()); + } + @DisplayName("로그인 실패 - 아이디 틀림") + @Test + public void SignInFailUsername(){ + //given + Member member = memberService.join(new Member("testUsername", "testPassword", "testNickName")); + MemberSignInDTO signInMemberDTO= new MemberSignInDTO("test","testPassword"); + //when + //then + Assertions.assertThatThrownBy(() -> memberService.SignIn(signInMemberDTO)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Username Mismatch"); + } + @DisplayName("로그인 실패 - 비밀번호 틀림") + @Test + public void SignInFailPassword(){ + //given + Member member = memberService.join(new Member("testUsername", "testPassword", "testNickName")); + MemberSignInDTO signInMemberDTO= new MemberSignInDTO("testUsername","test"); + //when + //then + Assertions.assertThatThrownBy(() -> memberService.SignIn(signInMemberDTO)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Password Mismatch"); + } +} diff --git a/src/test/java/com/swger/tddstudy/product/ProductControllerTest.java b/src/test/java/com/swger/tddstudy/product/ProductControllerTest.java new file mode 100644 index 0000000..e6e7e98 --- /dev/null +++ b/src/test/java/com/swger/tddstudy/product/ProductControllerTest.java @@ -0,0 +1,140 @@ +package com.swger.tddstudy.product; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.swger.tddstudy.member.domain.DTO.MemberDTO; +import com.swger.tddstudy.member.domain.Member; +import com.swger.tddstudy.member.service.MemberService; +import com.swger.tddstudy.product.domain.DTO.ProductRegisterDTO; +import com.swger.tddstudy.product.repository.ProductRepository; +import com.swger.tddstudy.product.service.ProductService; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.validation.BindException; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import javax.transaction.Transactional; + +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +public class ProductControllerTest { + + @Autowired + ProductRepository productRepository; + @Autowired + ProductService productService; + @Autowired + MemberService memberService; + @Autowired + MockMvc mockMvc; + @Autowired + ObjectMapper om; + + @DisplayName("상품 등록이 가능합니다") + @Test + public void registerSuccess() throws Exception { + //given + ProductRegisterDTO product = new ProductRegisterDTO("testName", 1000, 10); + Member member = memberService.SignUpAdmin(new MemberDTO("testUsername", + "testPassword", "testNickname", "testPassword")); + MockHttpSession session = new MockHttpSession(); + session.setAttribute("id", member.getId()); + //when, then + String content = om.writeValueAsString(product); + mockMvc.perform(post("/productRegister") + .session(session) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().string("Register OK")) + .andDo(print()); + + } + @DisplayName("상품 등록이 불가능합니다- 로그인을 하지 않음") + @Test + public void registerFailNotLogin() throws Exception { + //given + ProductRegisterDTO product = new ProductRegisterDTO("testName", 1000, 10); + MockHttpSession session = new MockHttpSession(); + //when, then + String content = om.writeValueAsString(product); + mockMvc.perform(post("/productRegister") + .session(session) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isBadRequest()) + .andExpect(content().string("You must SignIn")) + .andDo(print()); + + } + @DisplayName("상품 등록이 불가능합니다- Admin 계정이 아님") + @Test + public void registerFailNotAdmin() throws Exception { + //given + ProductRegisterDTO product = new ProductRegisterDTO("testName", 1000, 10); + Member member = memberService.SignUp(new MemberDTO("testUsername", + "testPassword", "testNickname", "testPassword")); + MockHttpSession session = new MockHttpSession(); + session.setAttribute("id", member.getId()); + //when, then + String content = om.writeValueAsString(product); + mockMvc.perform(post("/productRegister") + .session(session) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isBadRequest()) + .andExpect(content().string("You are not Admin")) + .andDo(print()); + + } + + + @DisplayName("상품 등록이 불가능합니다 - NotBlank") + @Test + public void registerFailNotBlank() throws Exception { + //given + ProductRegisterDTO product = new ProductRegisterDTO(null, 1000, 10); + //when, then + String content = om.writeValueAsString(product); + mockMvc.perform(post("/productRegister") + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(result -> assertTrue(result.getResolvedException() + .getClass().isAssignableFrom(BindException.class))) + .andDo(print()); + } + + @DisplayName("상품 등록이 불가능합니다 - Min") + @Test + public void registerFailMin() throws Exception { + //given + ProductRegisterDTO product = new ProductRegisterDTO("testname", 10000, 0); + //when, then + String content = om.writeValueAsString(product); + mockMvc.perform(post("/productRegister") + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(result -> assertTrue(result.getResolvedException() + .getClass().isAssignableFrom(BindException.class))) + .andDo(print()); + } + +} diff --git a/src/test/java/com/swger/tddstudy/product/ProductServiceTest.java b/src/test/java/com/swger/tddstudy/product/ProductServiceTest.java new file mode 100644 index 0000000..a30b992 --- /dev/null +++ b/src/test/java/com/swger/tddstudy/product/ProductServiceTest.java @@ -0,0 +1,70 @@ +package com.swger.tddstudy.product; + +import com.swger.tddstudy.product.domain.DTO.ProductRegisterDTO; +import com.swger.tddstudy.product.domain.Product; +import com.swger.tddstudy.product.repository.ProductRepository; +import com.swger.tddstudy.product.service.ProductService; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import javax.transaction.Transactional; +import java.util.Optional; + + +@SpringBootTest +@Transactional +public class ProductServiceTest { + + @Autowired + ProductService productService; + @Autowired + ProductRepository productRepository; + + @DisplayName("상품 등록이 가능합니다") + @Test + public void productRegisterSuccess() { + //given + ProductRegisterDTO product = new ProductRegisterDTO("testName", 1000, 10); + //when + Product registeredProduct = productService.register(product); + Optional productOptional = productRepository.findById(registeredProduct.getId()); + //then + Assertions.assertThat(registeredProduct.getId()) + .isEqualTo(productOptional.get().getId()); + } + + + @DisplayName("상품 주문이 가능합니다") + @Test + public void sellingSuccess() { + //given + Product product = new Product("testName", 1000, 10); + //when, then + Assertions.assertThat(product.sellingOrNo()).isTrue(); + } + + @DisplayName("상품 주문이 불가능합니다 - 재고 부족1") + @Test + public void sellingFailAmount1() { + //given + Product product = new Product("testName", 1000, 0); + //when, then + Assertions.assertThat(product.sellingOrNo()).isFalse(); + } + + @DisplayName("상품 주문이 불가능합니다 - 재고 부족2") + @Test + public void sellingFailAmount2() { + //given + Product product = new Product("testName", 1000, 1); + //when + product.sellProduct(1); + //then + Assertions.assertThat(product.sellingOrNo()).isFalse(); + } + + +}