diff --git a/src/main/java/com/clova/anifriends/domain/volunteer/Volunteer.java b/src/main/java/com/clova/anifriends/domain/volunteer/Volunteer.java index 62cd2623d..e3e32fb98 100644 --- a/src/main/java/com/clova/anifriends/domain/volunteer/Volunteer.java +++ b/src/main/java/com/clova/anifriends/domain/volunteer/Volunteer.java @@ -1,6 +1,7 @@ package com.clova.anifriends.domain.volunteer; import com.clova.anifriends.domain.common.BaseTimeEntity; +import com.clova.anifriends.domain.volunteer.exception.VolunteerBadRequestException; import com.clova.anifriends.domain.volunteer.wrapper.VolunteerEmail; import com.clova.anifriends.domain.volunteer.wrapper.VolunteerGender; import com.clova.anifriends.domain.volunteer.wrapper.VolunteerName; @@ -17,6 +18,7 @@ import jakarta.persistence.Id; import jakarta.persistence.Table; import java.time.LocalDate; +import java.time.format.DateTimeParseException; @Entity @Table(name = "volunteer") @@ -55,18 +57,57 @@ protected Volunteer() { public Volunteer( String email, String password, - LocalDate birthDate, + String birthDate, String phoneNumber, String gender, - int temperature, String name ) { this.email = new VolunteerEmail(email); this.password = new VolunteerPassword(password); - this.birthDate = birthDate; + this.birthDate = validateBirthDate(birthDate); this.phoneNumber = new VolunteerPhoneNumber(phoneNumber); - this.gender = VolunteerGender.valueOf(gender); - this.temperature = new VolunteerTemperature(temperature); + this.gender = VolunteerGender.from(gender); + this.temperature = new VolunteerTemperature(36); this.name = new VolunteerName(name); } + + private LocalDate validateBirthDate(String birthDate) { + try { + return LocalDate.parse(birthDate); + } catch (DateTimeParseException e) { + throw new VolunteerBadRequestException("생년월일 형식이 맞지 않습니다."); + } + } + + public Long getVolunteerId() { + return volunteerId; + } + + public String getEmail() { + return this.email.getEmail(); + } + + public String getPassword() { + return this.password.getPassword(); + } + + public LocalDate getBirthDate() { + return birthDate; + } + + public String getPhoneNumber() { + return this.phoneNumber.getPhoneNumber(); + } + + public String getGender() { + return this.gender.getName(); + } + + public Integer getTemperature() { + return this.temperature.getTemperature(); + } + + public String getName() { + return this.name.getName(); + } } diff --git a/src/main/java/com/clova/anifriends/domain/volunteer/VolunteerImage.java b/src/main/java/com/clova/anifriends/domain/volunteer/VolunteerImage.java index 7e9177ff9..01aae90a2 100644 --- a/src/main/java/com/clova/anifriends/domain/volunteer/VolunteerImage.java +++ b/src/main/java/com/clova/anifriends/domain/volunteer/VolunteerImage.java @@ -10,8 +10,10 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; +import lombok.Getter; @Entity +@Getter @Table(name = "voulunteer_image") public class VolunteerImage extends BaseTimeEntity { @@ -27,4 +29,7 @@ public class VolunteerImage extends BaseTimeEntity { @Column(name = "image_url") private String imageUrl; + protected VolunteerImage() { + } + } diff --git a/src/main/java/com/clova/anifriends/domain/volunteer/controller/VolunteerController.java b/src/main/java/com/clova/anifriends/domain/volunteer/controller/VolunteerController.java new file mode 100644 index 000000000..92f13a305 --- /dev/null +++ b/src/main/java/com/clova/anifriends/domain/volunteer/controller/VolunteerController.java @@ -0,0 +1,31 @@ +package com.clova.anifriends.domain.volunteer.controller; + +import com.clova.anifriends.domain.volunteer.dto.request.RegisterVolunteerRequest; +import com.clova.anifriends.domain.volunteer.service.VolunteerService; +import jakarta.validation.Valid; +import java.net.URI; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/volunteers") +public class VolunteerController { + + private final VolunteerService volunteerService; + private static final String BASE_URI = "/api/volunteers/"; + + @PostMapping + public ResponseEntity registerVolunteer( + @RequestBody @Valid RegisterVolunteerRequest registerVolunteerRequest + ) { + Long registeredVolunteerID = volunteerService.registerVolunteer(registerVolunteerRequest); + URI location = URI.create(BASE_URI + registeredVolunteerID); + return ResponseEntity.created(location).build(); + } + +} diff --git a/src/main/java/com/clova/anifriends/domain/volunteer/dto/request/RegisterVolunteerRequest.java b/src/main/java/com/clova/anifriends/domain/volunteer/dto/request/RegisterVolunteerRequest.java new file mode 100644 index 000000000..f5e12287e --- /dev/null +++ b/src/main/java/com/clova/anifriends/domain/volunteer/dto/request/RegisterVolunteerRequest.java @@ -0,0 +1,14 @@ +package com.clova.anifriends.domain.volunteer.dto.request; + +import jakarta.validation.constraints.NotBlank; + +public record RegisterVolunteerRequest( + @NotBlank(message = "이메일은 필수 항목입니다.") String email, + @NotBlank(message = "비밀번호는 필수 항목입니다.") String password, + @NotBlank(message = "이름은 필수 항목입니다.") String name, + @NotBlank(message = "생년월일은 필수 항목입니다.") String birthDate, + @NotBlank(message = "전화번호는 필수 항목입니다.") String phoneNumber, + @NotBlank(message = "성별은 필수 항목입니다.") String gender +) { + +} diff --git a/src/main/java/com/clova/anifriends/domain/volunteer/exception/NotFoundVolunteerGenderException.java b/src/main/java/com/clova/anifriends/domain/volunteer/exception/NotFoundVolunteerGenderException.java new file mode 100644 index 000000000..34c392fca --- /dev/null +++ b/src/main/java/com/clova/anifriends/domain/volunteer/exception/NotFoundVolunteerGenderException.java @@ -0,0 +1,10 @@ +package com.clova.anifriends.domain.volunteer.exception; + +import com.clova.anifriends.global.exception.NotFoundException; + +public class NotFoundVolunteerGenderException extends NotFoundException { + + public NotFoundVolunteerGenderException(String message) { + super(message); + } +} diff --git a/src/main/java/com/clova/anifriends/domain/volunteer/exception/VolunteerBadRequestException.java b/src/main/java/com/clova/anifriends/domain/volunteer/exception/VolunteerBadRequestException.java new file mode 100644 index 000000000..d3e4f8eff --- /dev/null +++ b/src/main/java/com/clova/anifriends/domain/volunteer/exception/VolunteerBadRequestException.java @@ -0,0 +1,10 @@ +package com.clova.anifriends.domain.volunteer.exception; + +import com.clova.anifriends.global.exception.BadRequestException; + +public class VolunteerBadRequestException extends BadRequestException { + + public VolunteerBadRequestException(String message) { + super(message); + } +} diff --git a/src/main/java/com/clova/anifriends/domain/volunteer/repository/VolunteerImageRepository.java b/src/main/java/com/clova/anifriends/domain/volunteer/repository/VolunteerImageRepository.java new file mode 100644 index 000000000..cae46f503 --- /dev/null +++ b/src/main/java/com/clova/anifriends/domain/volunteer/repository/VolunteerImageRepository.java @@ -0,0 +1,8 @@ +package com.clova.anifriends.domain.volunteer.repository; + +import com.clova.anifriends.domain.volunteer.VolunteerImage; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface VolunteerImageRepository extends JpaRepository { + +} diff --git a/src/main/java/com/clova/anifriends/domain/volunteer/service/VolunteerService.java b/src/main/java/com/clova/anifriends/domain/volunteer/service/VolunteerService.java new file mode 100644 index 000000000..7e261a308 --- /dev/null +++ b/src/main/java/com/clova/anifriends/domain/volunteer/service/VolunteerService.java @@ -0,0 +1,30 @@ +package com.clova.anifriends.domain.volunteer.service; + +import com.clova.anifriends.domain.volunteer.Volunteer; +import com.clova.anifriends.domain.volunteer.dto.request.RegisterVolunteerRequest; +import com.clova.anifriends.domain.volunteer.repository.VolunteerRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class VolunteerService { + + private final VolunteerRepository volunteerRepository; + + @Transactional + public Long registerVolunteer(RegisterVolunteerRequest registerVolunteerRequest) { + Volunteer volunteer = new Volunteer( + registerVolunteerRequest.email(), + registerVolunteerRequest.password(), + registerVolunteerRequest.birthDate(), + registerVolunteerRequest.phoneNumber(), + registerVolunteerRequest.gender(), + registerVolunteerRequest.name() + ); + + volunteerRepository.save(volunteer); + return volunteer.getVolunteerId(); + } +} diff --git a/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerEmail.java b/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerEmail.java index ee82b60fe..980040b67 100644 --- a/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerEmail.java +++ b/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerEmail.java @@ -1,8 +1,13 @@ package com.clova.anifriends.domain.volunteer.wrapper; +import com.clova.anifriends.domain.volunteer.exception.VolunteerBadRequestException; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import lombok.Getter; +@Getter @Embeddable public class VolunteerEmail { @@ -13,7 +18,23 @@ protected VolunteerEmail() { } public VolunteerEmail(String value) { + validateVolunteerEmail(value); this.email = value; } + private void validateVolunteerEmail(String email) { + if (email == null || email.isBlank()) { + throw new VolunteerBadRequestException("이메일은 필수 항목입니다."); + } + + String pattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"; + + Pattern emailPattern = Pattern.compile(pattern); + Matcher matcher = emailPattern.matcher(email); + + if (!matcher.matches()) { + throw new VolunteerBadRequestException("이메일 형식에 맞지 않습니다."); + } + } + } diff --git a/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerGender.java b/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerGender.java index 9eb70f053..a8196e4a9 100644 --- a/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerGender.java +++ b/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerGender.java @@ -1,6 +1,8 @@ package com.clova.anifriends.domain.volunteer.wrapper; import com.clova.anifriends.EnumType; +import com.clova.anifriends.domain.volunteer.exception.NotFoundVolunteerGenderException; +import java.util.Arrays; public enum VolunteerGender implements EnumType { @@ -17,4 +19,11 @@ public String getName() { public String getValue() { return this.name(); } + + public static VolunteerGender from(String gender) { + return Arrays.stream(VolunteerGender.values()) + .filter(volunteerGender -> volunteerGender.name().equalsIgnoreCase(gender)) + .findAny() + .orElseThrow(() -> new NotFoundVolunteerGenderException("존재하지 않는 성별입니다.")); + } } diff --git a/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerName.java b/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerName.java index ceaaa1637..a298d72fa 100644 --- a/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerName.java +++ b/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerName.java @@ -1,11 +1,16 @@ package com.clova.anifriends.domain.volunteer.wrapper; +import com.clova.anifriends.domain.volunteer.exception.VolunteerBadRequestException; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; +import lombok.Getter; +@Getter @Embeddable public class VolunteerName { + private static final int MAX_VOLUNTEER_NAME_LENGTH = 10; + @Column(name = "name") private String name; @@ -13,7 +18,17 @@ protected VolunteerName() { } public VolunteerName(String value) { + validateVolunteerName(value); this.name = value; } + private void validateVolunteerName(String name) { + if (name == null || name.isBlank()) { + throw new VolunteerBadRequestException("이름은 필수 항목입니다."); + } + + if (name.length() > MAX_VOLUNTEER_NAME_LENGTH) { + throw new VolunteerBadRequestException("이름은 최대 10자입니다."); + } + } } diff --git a/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerPassword.java b/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerPassword.java index 35c6c4ab5..181e792cf 100644 --- a/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerPassword.java +++ b/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerPassword.java @@ -1,11 +1,17 @@ package com.clova.anifriends.domain.volunteer.wrapper; +import com.clova.anifriends.domain.volunteer.exception.VolunteerBadRequestException; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; +import lombok.Getter; +@Getter @Embeddable public class VolunteerPassword { + private static final int MIN_PASSWORD_LENGTH = 6; + private static final int MAX_PASSWORD_LENGTH = 16; + @Column(name = "password") private String password; @@ -13,7 +19,13 @@ protected VolunteerPassword() { } public VolunteerPassword(String value) { + validateVolunteerPassword(value); this.password = value; } + private void validateVolunteerPassword(String password) { + if (password.length() < MIN_PASSWORD_LENGTH || password.length() > MAX_PASSWORD_LENGTH) { + throw new VolunteerBadRequestException("비밀번호는 최소 6자, 최대 16자입니다."); + } + } } diff --git a/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerPhoneNumber.java b/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerPhoneNumber.java index 9afc225e1..9ad2e51f9 100644 --- a/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerPhoneNumber.java +++ b/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerPhoneNumber.java @@ -1,11 +1,17 @@ package com.clova.anifriends.domain.volunteer.wrapper; +import com.clova.anifriends.domain.volunteer.exception.VolunteerBadRequestException; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; +import lombok.Getter; +@Getter @Embeddable public class VolunteerPhoneNumber { + private static final int MIN_PHONE_NUMBER_LENGTH = 9; + private static final int MAX_PHONE_NUMBER_LENGTH = 11; + @Column(name = "phone_number") private String phoneNumber; @@ -13,6 +19,14 @@ protected VolunteerPhoneNumber() { } public VolunteerPhoneNumber(String value) { + validateVolunteerPhoneNumber(value); this.phoneNumber = value; } + + private void validateVolunteerPhoneNumber(String phoneNumber) { + if (phoneNumber.length() < MIN_PHONE_NUMBER_LENGTH + || phoneNumber.length() > MAX_PHONE_NUMBER_LENGTH) { + throw new VolunteerBadRequestException("전화번호는 최소 9자, 최대 11자입니다."); + } + } } diff --git a/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerTemperature.java b/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerTemperature.java index 047463e97..e10c8e31e 100644 --- a/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerTemperature.java +++ b/src/main/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerTemperature.java @@ -1,11 +1,16 @@ package com.clova.anifriends.domain.volunteer.wrapper; +import com.clova.anifriends.domain.volunteer.exception.VolunteerBadRequestException; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; +import lombok.Getter; +@Getter @Embeddable public class VolunteerTemperature { + private static final int MAX_VOLUNTEER_TEMPERATURE = 99; + @Column(name = "temperature") private Integer temperature; @@ -13,7 +18,13 @@ protected VolunteerTemperature() { } public VolunteerTemperature(int value) { + validateVolunteerTemperature(value); this.temperature = value; } + private void validateVolunteerTemperature(int temperature) { + if (temperature > MAX_VOLUNTEER_TEMPERATURE) { + throw new VolunteerBadRequestException("봉사자 체온은 99도 이하입니다."); + } + } } diff --git a/src/test/java/com/clova/anifriends/base/BaseControllerTest.java b/src/test/java/com/clova/anifriends/base/BaseControllerTest.java index 539f99d57..e79aaba36 100644 --- a/src/test/java/com/clova/anifriends/base/BaseControllerTest.java +++ b/src/test/java/com/clova/anifriends/base/BaseControllerTest.java @@ -3,11 +3,13 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import com.clova.anifriends.base.config.RestDocsConfig; +import com.clova.anifriends.domain.volunteer.service.VolunteerService; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; import org.springframework.restdocs.RestDocumentationContextProvider; import org.springframework.restdocs.RestDocumentationExtension; @@ -31,6 +33,9 @@ public abstract class BaseControllerTest { @Autowired protected RestDocumentationResultHandler restDocs; + @MockBean + protected VolunteerService volunteerService; + @BeforeEach void setUp( WebApplicationContext applicationContext, diff --git a/src/test/java/com/clova/anifriends/domain/volunteer/VolunteerTest.java b/src/test/java/com/clova/anifriends/domain/volunteer/VolunteerTest.java new file mode 100644 index 000000000..45b68f6f1 --- /dev/null +++ b/src/test/java/com/clova/anifriends/domain/volunteer/VolunteerTest.java @@ -0,0 +1,52 @@ +package com.clova.anifriends.domain.volunteer; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.clova.anifriends.domain.volunteer.exception.VolunteerBadRequestException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class VolunteerTest { + + @Nested + @DisplayName("Volunteer 생성 시") + class newVolunteerTest { + + String email = "asdf@gmail.com"; + String password = "asdf1234"; + String birthDate; + String phoneNumber = "01012341234"; + String gender = "MALE"; + String name = "홍길동"; + + @Test + @DisplayName("성공") + void success() { + // given + birthDate = "1990-01-01"; + + // when + Volunteer volunteer = new Volunteer(email, password, birthDate, phoneNumber, gender, + name); + + // then + assertThat(volunteer.getEmail()).isEqualTo(email); + } + + @Test + @DisplayName("예외: 생년월일 형식이 잘못된 경우") + void throwExceptionWhenBirthDateFormatIsWrong() { + // given + birthDate = "1990:01:12"; + + // when + // then + assertThatThrownBy(() -> new Volunteer(email, password, birthDate, phoneNumber, gender, + name)) + .isInstanceOf(VolunteerBadRequestException.class); + } + } + +} \ No newline at end of file diff --git a/src/test/java/com/clova/anifriends/domain/volunteer/controller/VolunteerControllerTest.java b/src/test/java/com/clova/anifriends/domain/volunteer/controller/VolunteerControllerTest.java new file mode 100644 index 000000000..be32f1f29 --- /dev/null +++ b/src/test/java/com/clova/anifriends/domain/volunteer/controller/VolunteerControllerTest.java @@ -0,0 +1,52 @@ +package com.clova.anifriends.domain.volunteer.controller; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.responseHeaders; +import static org.springframework.restdocs.payload.JsonFieldType.STRING; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.clova.anifriends.base.BaseControllerTest; +import com.clova.anifriends.domain.volunteer.dto.request.RegisterVolunteerRequest; +import com.clova.anifriends.domain.volunteer.support.VolunteerDtoFixture; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.ResultActions; + +class VolunteerControllerTest extends BaseControllerTest { + + @Test + @DisplayName("봉사자 회원가입 API 호출 시") + void registerVolunteer() throws Exception { + // given + RegisterVolunteerRequest registerVolunteerRequest = VolunteerDtoFixture.registerVolunteerRequest(); + given(volunteerService.registerVolunteer(any())).willReturn(1L); + + // when + ResultActions resultActions = mockMvc.perform( + post("/api/volunteers") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(registerVolunteerRequest))); + + // then + resultActions.andExpect(status().isCreated()) + .andDo(restDocs.document( + requestFields( + fieldWithPath("email").type(STRING).description("이메일"), + fieldWithPath("password").type(STRING).description("비밀번호"), + fieldWithPath("name").type(STRING).description("이름"), + fieldWithPath("birthDate").type(STRING).description("생년월일"), + fieldWithPath("phoneNumber").type(STRING).description("전화번호"), + fieldWithPath("gender").type(STRING).description("성별") + ), + responseHeaders( + headerWithName("Location").description("생성된 리소스 위치") + ) + )); + } +} diff --git a/src/test/java/com/clova/anifriends/domain/volunteer/service/VolunteerServiceTest.java b/src/test/java/com/clova/anifriends/domain/volunteer/service/VolunteerServiceTest.java new file mode 100644 index 000000000..6859f44e1 --- /dev/null +++ b/src/test/java/com/clova/anifriends/domain/volunteer/service/VolunteerServiceTest.java @@ -0,0 +1,50 @@ +package com.clova.anifriends.domain.volunteer.service; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; + +import com.clova.anifriends.domain.volunteer.Volunteer; +import com.clova.anifriends.domain.volunteer.dto.request.RegisterVolunteerRequest; +import com.clova.anifriends.domain.volunteer.repository.VolunteerRepository; +import com.clova.anifriends.domain.volunteer.support.VolunteerDtoFixture; +import com.clova.anifriends.domain.volunteer.support.VolunteerFixture; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class VolunteerServiceTest { + + @InjectMocks + VolunteerService volunteerService; + + @Mock + VolunteerRepository volunteerRepository; + + @Nested + @DisplayName("registerVolunteer 메서드 실행 시") + class RegisterVolunteerTest { + + Volunteer volunteer = VolunteerFixture.volunteer(); + + @Test + @DisplayName("성공") + void success() { + // given + given(volunteerRepository.save(any())).willReturn(volunteer); + RegisterVolunteerRequest registerVolunteerRequest = VolunteerDtoFixture.registerVolunteerRequest(); + + // when + volunteerService.registerVolunteer(registerVolunteerRequest); + + // then + then(volunteerRepository).should().save(any()); + } + } + +} \ No newline at end of file diff --git a/src/test/java/com/clova/anifriends/domain/volunteer/support/VolunteerDtoFixture.java b/src/test/java/com/clova/anifriends/domain/volunteer/support/VolunteerDtoFixture.java new file mode 100644 index 000000000..94b16e856 --- /dev/null +++ b/src/test/java/com/clova/anifriends/domain/volunteer/support/VolunteerDtoFixture.java @@ -0,0 +1,21 @@ +package com.clova.anifriends.domain.volunteer.support; + +import com.clova.anifriends.domain.volunteer.dto.request.RegisterVolunteerRequest; +import com.clova.anifriends.domain.volunteer.wrapper.VolunteerGender; + +public class VolunteerDtoFixture { + + private static final Long VOLUNTEER_ID = 1L; + private static final String EMAIL = "asdf@gmail.com"; + private static final String PASSWORD = "asdf1234"; + private static final String BIRTH_DATE = "1999-03-23"; + private static final String PHONE_NUMBER = "01012345678"; + private static final String GENDER = VolunteerGender.MALE.getName(); + private static final Integer TEMPERATURE = 36; + private static final String NAME = "김봉사"; + + public static RegisterVolunteerRequest registerVolunteerRequest() { + return new RegisterVolunteerRequest(EMAIL, PASSWORD, NAME, BIRTH_DATE, PHONE_NUMBER, + GENDER); + } +} diff --git a/src/test/java/com/clova/anifriends/domain/volunteer/support/VolunteerFixture.java b/src/test/java/com/clova/anifriends/domain/volunteer/support/VolunteerFixture.java new file mode 100644 index 000000000..1664f8d18 --- /dev/null +++ b/src/test/java/com/clova/anifriends/domain/volunteer/support/VolunteerFixture.java @@ -0,0 +1,20 @@ +package com.clova.anifriends.domain.volunteer.support; + +import com.clova.anifriends.domain.volunteer.Volunteer; +import com.clova.anifriends.domain.volunteer.wrapper.VolunteerGender; + +public class VolunteerFixture { + + private static final Long VOLUNTEER_ID = 1L; + private static final String EMAIL = "asdf@gmail.com"; + private static final String PASSWORD = "asdf1234"; + private static final String BIRTH_DATE = "1999-03-23"; + private static final String PHONE_NUMBER = "01012345678"; + private static final String GENDER = VolunteerGender.MALE.getName(); + private static final Integer TEMPERATURE = 36; + private static final String NAME = "김봉사"; + + public static Volunteer volunteer() { + return new Volunteer(EMAIL, PASSWORD, BIRTH_DATE, PHONE_NUMBER, GENDER, NAME); + } +} diff --git a/src/test/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerEmailTest.java b/src/test/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerEmailTest.java new file mode 100644 index 000000000..1e718363a --- /dev/null +++ b/src/test/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerEmailTest.java @@ -0,0 +1,68 @@ +package com.clova.anifriends.domain.volunteer.wrapper; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.clova.anifriends.domain.volunteer.exception.VolunteerBadRequestException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class VolunteerEmailTest { + + @Nested + @DisplayName("VolunteerEmail 생성 시") + class newVolunteerEmailTest { + + String email; + + @Test + @DisplayName("성공") + void success() { + // given + email = "asdf@gmail.com"; + + // when + VolunteerEmail volunteerEmail = new VolunteerEmail(email); + + // then + assertThat(volunteerEmail.getEmail()).isEqualTo(email); + } + + @Test + @DisplayName("예외: 이메일이 null인 경우") + void throwExceptionWhenEmailIsNull() { + // given + email = null; + + // when + // then + assertThatThrownBy(() -> new VolunteerEmail(email)) + .isInstanceOf(VolunteerBadRequestException.class); + } + + @Test + @DisplayName("예외: 이메일이 blank인 경우") + void throwExceptionWhenEmailIsBlank() { + // given + email = " "; + + // when + // then + assertThatThrownBy(() -> new VolunteerEmail(email)) + .isInstanceOf(VolunteerBadRequestException.class); + } + + @Test + @DisplayName("예외: 이메일 형식에 맞지 않는 경우") + void throwExceptionWhenEmailIsNotMatched() { + // given + email = "asdfnaver.com"; + + // when + // then + assertThatThrownBy(() -> new VolunteerEmail(email)) + .isInstanceOf(VolunteerBadRequestException.class); + } + } +} diff --git a/src/test/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerGenderTest.java b/src/test/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerGenderTest.java new file mode 100644 index 000000000..17ebfd9e9 --- /dev/null +++ b/src/test/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerGenderTest.java @@ -0,0 +1,56 @@ +package com.clova.anifriends.domain.volunteer.wrapper; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.clova.anifriends.domain.volunteer.exception.NotFoundVolunteerGenderException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class VolunteerGenderTest { + + @Nested + @DisplayName("VolunteerGender ") + class matchVolunteerGenderTest { + + String gender; + + @Test + @DisplayName("성공") + void success() { + // given + gender = "MALE"; + + // when + VolunteerGender volunteerGender = VolunteerGender.from(gender); + + // then + assertThat(volunteerGender.getName()).isEqualTo(gender); + } + + @Test + @DisplayName("예외: VolunteerGender가 null인 경우") + void throwExceptionWhenVolunteerGenderIsNull() { + // given + gender = null; + + // when + // then + assertThatThrownBy(() -> VolunteerGender.from(gender)) + .isInstanceOf(NotFoundVolunteerGenderException.class); + } + + @Test + @DisplayName("예외: VolunteerGender가 다른 문자열인 경우") + void throwExceptionWhenVolunteerGenderIsWrong() { + // given + gender = "ABCD"; + + // when + // then + assertThatThrownBy(() -> VolunteerGender.from(gender)) + .isInstanceOf(NotFoundVolunteerGenderException.class); + } + } +} \ No newline at end of file diff --git a/src/test/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerNameTest.java b/src/test/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerNameTest.java new file mode 100644 index 000000000..7a352afd7 --- /dev/null +++ b/src/test/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerNameTest.java @@ -0,0 +1,68 @@ +package com.clova.anifriends.domain.volunteer.wrapper; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.clova.anifriends.domain.volunteer.exception.VolunteerBadRequestException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class VolunteerNameTest { + + @Nested + @DisplayName("VolunteerName 생성 시") + class newVolunteerNameTest { + + String name; + + @Test + @DisplayName("성공") + void success() { + // given + name = "홍길동"; + + // when + VolunteerName volunteerName = new VolunteerName(name); + + // then + assertThat(volunteerName.getName()).isEqualTo(name); + } + + @Test + @DisplayName("예외: 이름이 null인 경우") + void throwExceptionWhenNameIsNull() { + // given + name = null; + + // when + // then + assertThatThrownBy(() -> new VolunteerName(name)) + .isInstanceOf(VolunteerBadRequestException.class); + } + + @Test + @DisplayName("예외: 이름이 blank인 경우") + void throwExceptionWhenNameIsBlank() { + // given + name = " "; + + // when + // then + assertThatThrownBy(() -> new VolunteerName(name)) + .isInstanceOf(VolunteerBadRequestException.class); + } + + @Test + @DisplayName("예외: 이름이 10자 초과인 경우") + void throwExceptionWhenNameIsMoreThanTen() { + // given + name = "abcdefghijk"; + + // when + // then + assertThatThrownBy(() -> new VolunteerName(name)) + .isInstanceOf(VolunteerBadRequestException.class); + } + } +} \ No newline at end of file diff --git a/src/test/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerPasswordTest.java b/src/test/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerPasswordTest.java new file mode 100644 index 000000000..6938a7a0d --- /dev/null +++ b/src/test/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerPasswordTest.java @@ -0,0 +1,56 @@ +package com.clova.anifriends.domain.volunteer.wrapper; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.clova.anifriends.domain.volunteer.exception.VolunteerBadRequestException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class VolunteerPasswordTest { + + @Nested + @DisplayName("VolunteerPassword 생성 시") + class newVolunteerPasswordTest { + + String password; + + @Test + @DisplayName("성공") + void success() { + // given + password = "asdfqwer123"; + + // when + VolunteerPassword volunteerPassword = new VolunteerPassword(password); + + // then + assertThat(volunteerPassword.getPassword()).isEqualTo(password); + } + + @Test + @DisplayName("예외: 비밀번호가 6자 미만인 경우") + void throwExceptionWhenPasswordIsLessThanSix() { + // given + password = "asdf"; + + // when + // then + assertThatThrownBy(() -> new VolunteerPassword(password)) + .isInstanceOf(VolunteerBadRequestException.class); + } + + @Test + @DisplayName("예외: 비밀번호가 16자 초과인 경우") + void throwExceptionWhenPasswordIsOverThanSixteen() { + // given + password = "asdfqwer123asdfqwer123"; + + // when + // then + assertThatThrownBy(() -> new VolunteerPassword(password)) + .isInstanceOf(VolunteerBadRequestException.class); + } + } +} \ No newline at end of file diff --git a/src/test/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerPhoneNumberTest.java b/src/test/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerPhoneNumberTest.java new file mode 100644 index 000000000..ed6cd6c01 --- /dev/null +++ b/src/test/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerPhoneNumberTest.java @@ -0,0 +1,56 @@ +package com.clova.anifriends.domain.volunteer.wrapper; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.clova.anifriends.domain.volunteer.exception.VolunteerBadRequestException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class VolunteerPhoneNumberTest { + + @Nested + @DisplayName("VolunteerPhoneNumber 생성 시") + class newVolunteerPhoneNumberTest { + + String phoneNumber; + + @Test + @DisplayName("성공") + void success() { + // given + phoneNumber = "01012345678"; + + // when + VolunteerPhoneNumber volunteerPhoneNumber = new VolunteerPhoneNumber(phoneNumber); + + // then + assertThat(volunteerPhoneNumber.getPhoneNumber()).isEqualTo(phoneNumber); + } + + @Test + @DisplayName("예외: 전화번호가 9자 미만인 경우") + void throwExceptionWhenPhoneNumberIsLessThan9() { + // given + phoneNumber = "01012345"; + + // when + // then + assertThatThrownBy(() -> new VolunteerPhoneNumber(phoneNumber)) + .isInstanceOf(VolunteerBadRequestException.class); + } + + @Test + @DisplayName("예외: 전화번호가 12자 초과인 경우") + void throwExceptionWhenPhoneNumberIsMoreThan12() { + // given + phoneNumber = "010123456789"; + + // when + // then + assertThatThrownBy(() -> new VolunteerPhoneNumber(phoneNumber)) + .isInstanceOf(VolunteerBadRequestException.class); + } + } +} diff --git a/src/test/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerTemperatureTest.java b/src/test/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerTemperatureTest.java new file mode 100644 index 000000000..fa0ea9a81 --- /dev/null +++ b/src/test/java/com/clova/anifriends/domain/volunteer/wrapper/VolunteerTemperatureTest.java @@ -0,0 +1,44 @@ +package com.clova.anifriends.domain.volunteer.wrapper; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.clova.anifriends.domain.volunteer.exception.VolunteerBadRequestException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class VolunteerTemperatureTest { + + @Nested + @DisplayName("VolunteerTemperature 생성 시") + class newVolunteerTemperatureTest { + + int temperature; + + @Test + @DisplayName("성공") + void success() { + // given + temperature = 36; + + // when + VolunteerTemperature volunteerTemperature = new VolunteerTemperature(temperature); + + // then + assertThat(volunteerTemperature.getTemperature()).isEqualTo(temperature); + } + + @Test + @DisplayName("예외: 봉사자 체온이 99도 초과인 경우") + void throwExceptionWhenVolunteerTemperatureIsOver99() { + // given + temperature = 101; + + // when + // then + assertThatThrownBy(() -> new VolunteerTemperature(temperature)) + .isInstanceOf(VolunteerBadRequestException.class); + } + } +} \ No newline at end of file