diff --git a/datajpatest/pom.xml b/datajpatest/pom.xml
index b06b907..98580d8 100644
--- a/datajpatest/pom.xml
+++ b/datajpatest/pom.xml
@@ -29,7 +29,17 @@
org.springframework.boot
spring-boot-starter-web
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ 2.5.3
+
+
+ org.hibernate.validator
+ hibernate-validator
+ 6.2.0.Final
+
javax.validation
validation-api
@@ -76,6 +86,12 @@
1.4.200
test
+
+ org.spockframework
+ spock-core
+ RELEASE
+ test
+
diff --git a/datajpatest/src/main/java/com/example/datajpatest/controller/MemberController.java b/datajpatest/src/main/java/com/example/datajpatest/controller/MemberController.java
index 1ee297b..f34c566 100644
--- a/datajpatest/src/main/java/com/example/datajpatest/controller/MemberController.java
+++ b/datajpatest/src/main/java/com/example/datajpatest/controller/MemberController.java
@@ -7,6 +7,7 @@
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
+import javax.validation.Valid;
import java.net.URI;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
@@ -22,7 +23,7 @@ public MemberController(MemberRepository memberRepository) {
}
@PostMapping("/member")
- public ResponseEntity joinMember(@RequestBody MemberJoinRequest request) {
+ public ResponseEntity joinMember(@Valid @RequestBody MemberJoinRequest request) {
MemberJpaEntity entity = MemberJpaEntity.from(request);
MemberJpaEntity saved = memberRepository.save(entity);
final Long memberId = saved.getId();
diff --git a/datajpatest/src/main/java/com/example/datajpatest/controller/MemberJoinRequest.java b/datajpatest/src/main/java/com/example/datajpatest/controller/MemberJoinRequest.java
index a88cb44..84d675c 100644
--- a/datajpatest/src/main/java/com/example/datajpatest/controller/MemberJoinRequest.java
+++ b/datajpatest/src/main/java/com/example/datajpatest/controller/MemberJoinRequest.java
@@ -2,17 +2,21 @@
import com.example.datajpatest.model.Member;
import lombok.Getter;
+import lombok.Setter;
-import java.beans.ConstructorProperties;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
@Getter
+@Setter
public class MemberJoinRequest implements Member {
- private final Long id;
- private final String name;
+ @NotNull
+ private Long id;
+ @NotBlank
+ private String name;
+ @NotNull
+ @Pattern(regexp = "[0-9]{10}|[0-9]{3}-[0-9]{2}-[0-9]{5}", message = "10자리의 숫자 또는 대시를 포함한 12자리의 숫자만 입력가능합니다.")
+ private String businessNumber;
- @ConstructorProperties({"id", "name"})
- public MemberJoinRequest(Long id, String name) {
- this.id = id;
- this.name = name;
- }
}
diff --git a/datajpatest/src/test/java/com/example/datajpatest/controller/MemberJoinRequestSpec.groovy b/datajpatest/src/test/java/com/example/datajpatest/controller/MemberJoinRequestSpec.groovy
new file mode 100644
index 0000000..8635a86
--- /dev/null
+++ b/datajpatest/src/test/java/com/example/datajpatest/controller/MemberJoinRequestSpec.groovy
@@ -0,0 +1,114 @@
+package com.example.datajpatest.controller
+
+import spock.lang.Shared
+import spock.lang.Specification
+import spock.lang.Subject
+import spock.lang.Unroll
+
+import javax.validation.ConstraintViolation
+import javax.validation.Validation
+import javax.validation.Validator
+import javax.validation.ValidatorFactory
+
+class MemberJoinRequestSpec extends Specification {
+
+ @Subject
+ private MemberJoinRequest sut
+
+ @Shared
+ private Validator validator
+
+ def setupSpec() {
+ ValidatorFactory factory = Validation.buildDefaultValidatorFactory()
+ validator = factory.getValidator()
+ }
+
+ def setup() {
+ sut = getNoConstraintValidationMemberJoinRequest()
+ }
+
+ @Unroll
+ def "사업자 등록번호가 #testBusinessNumber 를 허용한다."() {
+ given:
+ sut.setBusinessNumber(testBusinessNumber)
+
+ when:
+ Set> constraintViolations = validator.validate(sut)
+
+ then:
+ noConstraintViolation(constraintViolations)
+
+ where:
+ testBusinessNumber << ['1448125784', '144-81-25784']
+ }
+
+ def "사업자 등록번호는 null 을 허용하지 않는다."() {
+ given:
+ sut.setBusinessNumber(null)
+
+ when:
+ Set> constraintViolations = validator.validate(sut)
+
+ then:
+ constraintViolations.size() == 1
+ with(constraintViolations[0]) {
+ propertyPath.toString() == 'businessNumber'
+ invalidValue == null
+ messageTemplate == '{javax.validation.constraints.NotNull.message}'
+ }
+ }
+
+ @Unroll
+ def "사업자 등록번호는 #testBusinessNumber.length() 자리를 허용하지 않는다."() {
+ given:
+ sut.setBusinessNumber(testBusinessNumber)
+
+ when:
+ Set> constraintViolations = validator.validate(sut)
+
+ then:
+ constraintViolations.size() == 1
+ with(constraintViolations[0]) {
+ propertyPath.toString() == 'businessNumber'
+ invalidValue.toString() == testBusinessNumber
+ message == '10자리의 숫자 또는 대시를 포함한 12자리의 숫자만 입력가능합니다.'
+ }
+
+ where:
+ testBusinessNumber << ['', '1', '123456789', '12345678901', '1234567890123', '12345678901234']
+ }
+
+ @Unroll
+ def "사업자 등록번호는 문자열 #testBusinessNumber (#testBusinessNumber.length()) 을 허용하지 않는다."() {
+ given:
+ sut.setBusinessNumber(testBusinessNumber)
+
+ when:
+ Set> constraintViolations = validator.validate(sut)
+
+ then:
+ constraintViolations.size() == 1
+ with(constraintViolations[0]) {
+ propertyPath.toString() == 'businessNumber'
+ invalidValue.toString() == testBusinessNumber
+ message == '10자리의 숫자 또는 대시를 포함한 12자리의 숫자만 입력가능합니다.'
+ }
+
+ where:
+ testBusinessNumber << ['apple', 'tablelands']
+ }
+
+
+ static def getNoConstraintValidationMemberJoinRequest() {
+ def req = new MemberJoinRequest()
+ req.id = 1
+ req.name = "테스터"
+ req.businessNumber = "1234567890"
+ return req
+ }
+
+ static def noConstraintViolation(Set> constraintViolations) {
+ constraintViolations.isEmpty()
+ }
+
+}