Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/#56 회사 인증 테스트코드 작성 #61

Merged
merged 14 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@

@RestController
@RequiredArgsConstructor
@RequestMapping("/certification")
@RequestMapping("/api/v1/certification")
public class CertificationController {

private final CertificationService certificationService;

@PostMapping("/users/business-card")
@PostMapping("/users/me/company-info")
public ResponseEntity<Void> registerCompanyInfo(
@Login AuthInfo authInfo,
@RequestPart("companyEmail") @NotNull String companyEmail,
Expand All @@ -36,7 +36,7 @@ public ResponseEntity<Void> registerCompanyInfo(
return ResponseEntity.ok().build();
}

@PostMapping("/users/company-mail")
@PostMapping("/users/me/company-mail")
public ResponseEntity<Void> sendVerificationCodeByEmail(
@Login AuthInfo authInfo,
@Valid @RequestBody EmailDto.Request request
Expand All @@ -45,7 +45,7 @@ public ResponseEntity<Void> sendVerificationCodeByEmail(
return ResponseEntity.ok().build();
}

@PostMapping("/users/company-mail/verification")
@PostMapping("/users/me/company-mail/verification")
public ResponseEntity<Void> verifyEmail(
@Login AuthInfo authInfo,
@Valid @RequestBody VerificationCodeDto.Request request
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package coffeemeet.server.certification.domain;

import coffeemeet.server.common.util.Patterns;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.NonNull;

@Getter
@Embeddable
Expand All @@ -15,15 +15,8 @@ public class CompanyEmail {
@Column(name = "company_email")
private String value;

public CompanyEmail(String value) {
validateCompanyEmail(value);
public CompanyEmail(@NonNull String value) {
this.value = value;
}

private void validateCompanyEmail(String companyEmail) {
if (!Patterns.EMAIL_PATTERN.matcher(companyEmail).matches()) {
throw new IllegalArgumentException("올바르지 않은 이메일입니다.");
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.time.LocalDateTime;
import lombok.Getter;
import lombok.NonNull;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;

Expand All @@ -15,7 +16,8 @@ public class EmailVerification {
private String code;
private LocalDateTime createdAt;

public EmailVerification(Long userId, CompanyEmail companyEmail, String code) {
public EmailVerification(@NonNull Long userId, @NonNull CompanyEmail companyEmail,
@NonNull String code) {
this.userId = userId;
this.companyEmail = companyEmail;
this.code = code;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public void registerCertification(long userId, String email, String departmentNa
}

private void uploadBusinessCard(long userId, String key, File businessCardUrl) {
certificationQuery.applyIfCertifiedUser(userId, certification -> {
certificationCommand.applyIfCertifiedUser(userId, certification -> {
String oldKey = s3MediaService.extractKey(certification.getBusinessCardUrl(), BUSINESS_CARD);
s3MediaService.delete(oldKey);
});
Expand All @@ -57,7 +57,7 @@ private void uploadBusinessCard(long userId, String key, File businessCardUrl) {

public void sendVerificationMail(Long userId, String email) {
CompanyEmail companyEmail = new CompanyEmail(email);
certificationQuery.checkDuplicatedCompanyEmail(companyEmail);
certificationCommand.hasDuplicatedCompanyEmail(companyEmail);

String verificationCode = generateVerificationCode();
emailService.sendVerificationCode(companyEmail, verificationCode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import coffeemeet.server.certification.domain.Department;
import coffeemeet.server.certification.repository.CertificationRepository;
import coffeemeet.server.user.domain.User;
import java.util.function.Consumer;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -14,6 +15,8 @@
@RequiredArgsConstructor
public class CertificationCommand {

private static final String EXISTED_COMPANY_EMAIL = "이미 사용 중인 회사 이메일입니다.";

private final CertificationRepository certificationRepository;

public void newCertification(CompanyEmail companyEmail, String businessCardUrl,
Expand All @@ -28,4 +31,14 @@ public void newCertification(CompanyEmail companyEmail, String businessCardUrl,
);
}

public void hasDuplicatedCompanyEmail(CompanyEmail companyEmail) {
if (certificationRepository.existsByCompanyEmail(companyEmail)) {
throw new IllegalArgumentException(EXISTED_COMPANY_EMAIL);
}
}

public void applyIfCertifiedUser(Long userId, Consumer<? super Certification> consumer) {
certificationRepository.findByUserId(userId).ifPresent(consumer);
}

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package coffeemeet.server.certification.service.cq;

import coffeemeet.server.certification.domain.Certification;
import coffeemeet.server.certification.domain.CompanyEmail;
import coffeemeet.server.certification.repository.CertificationRepository;
import java.util.function.Consumer;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -13,8 +11,7 @@
@Transactional(readOnly = true)
public class CertificationQuery {

public static final String CERTIFICATION_NOT_FOUND = "해당 사용자의 인증정보를 찾을 수 없습니다.";
private static final String EXISTED_COMPANY_EMAIL = "이미 사용 중인 회사 이메일입니다.";
private static final String CERTIFICATION_NOT_FOUND = "해당 사용자의 인증정보를 찾을 수 없습니다.";

private final CertificationRepository certificationRepository;

Expand All @@ -23,14 +20,4 @@ public Certification getCertificationByUserId(Long userId) {
.orElseThrow(() -> new IllegalArgumentException(CERTIFICATION_NOT_FOUND));
}

public void checkDuplicatedCompanyEmail(CompanyEmail companyEmail) {
if (certificationRepository.existsByCompanyEmail(companyEmail)) {
throw new IllegalArgumentException(EXISTED_COMPANY_EMAIL);
}
}

public void applyIfCertifiedUser(Long userId, Consumer<? super Certification> consumer) {
certificationRepository.findByUserId(userId).ifPresent(consumer);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package coffeemeet.server.certification.controller;

import static coffeemeet.server.common.fixture.dto.RefreshTokenFixture.refreshToken;
import static coffeemeet.server.common.fixture.entity.CertificationFixture.department;
import static coffeemeet.server.common.fixture.entity.CertificationFixture.email;
import static coffeemeet.server.common.fixture.entity.CertificationFixture.emailDtoRequest;
import static coffeemeet.server.common.fixture.entity.CertificationFixture.verificationCodeDtoRequest;
import static com.epages.restdocs.apispec.MockMvcRestDocumentationWrapper.document;
import static com.epages.restdocs.apispec.MockMvcRestDocumentationWrapper.resourceDetails;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.BDDMockito.given;
import static org.springframework.http.HttpHeaders.AUTHORIZATION;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA;
import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName;
import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.multipart;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields;
import static org.springframework.restdocs.request.RequestDocumentation.partWithName;
import static org.springframework.restdocs.request.RequestDocumentation.requestParts;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import coffeemeet.server.auth.domain.RefreshToken;
import coffeemeet.server.auth.service.AuthService;
import coffeemeet.server.certification.service.CertificationService;
import coffeemeet.server.common.config.ControllerTestConfig;
import coffeemeet.server.oauth.service.OAuthService;
import java.util.Optional;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.mock.web.MockPart;

class CertificationControllerTest extends ControllerTestConfig {

@MockBean
protected AuthService authService;
@MockBean
protected OAuthService oAuthService; // TODO: 2023/10/30 authService, oAuthService Controller 테스트에서 전부 중복이라서 Config에 두는게 좋을 듯
@MockBean
private CertificationService certificationService;
private RefreshToken refreshToken;

@BeforeEach
void setUp() {
RefreshToken refreshToken = refreshToken();
given(refreshTokenRepository.findById(anyLong())).willReturn(Optional.ofNullable(refreshToken));
}

@Test
void registerCompanyInfoTest() throws Exception {
// given
String sBusinessCard = "businessCard";
String sCompanyEmail = "companyEmail";
String sDepartment = "department";
MockMultipartFile businessCardImage = new MockMultipartFile(
sBusinessCard,
"business_card.jpg",
"image/jpeg",
sBusinessCard.getBytes()
);

MockPart companyEmail = new MockPart(sCompanyEmail, email().getBytes());
MockPart department = new MockPart(sDepartment, department().name().getBytes());

// when, then
mockMvc.perform(multipart("/api/v1/certification/users/me/company-info")
.file("businessCard", businessCardImage.getBytes())
.part(companyEmail)
.part(department)
.header(AUTHORIZATION, TOKEN)
.contentType(MULTIPART_FORM_DATA)
)
.andExpect(status().isOk())
.andDo(document("certification-register",
resourceDetails().tag("회사 인증").description("회사 정보 등록"),
preprocessRequest(prettyPrint()),
preprocessResponse(prettyPrint()),
requestHeaders(
headerWithName(AUTHORIZATION).description("토큰")
),
requestParts(
partWithName(sBusinessCard).description("회사 명함 이미지"),
partWithName(sCompanyEmail).description("회사 이메일"),
partWithName(sDepartment).description("회사 부서명")
)
));
}

@Test
void sendVerificationCodeByEmailTest() throws Exception {
// given
String emailDtoRequest = objectMapper.writeValueAsString(emailDtoRequest());

// when, then
mockMvc.perform(post("/api/v1/certification/users/me/company-mail")
.header(AUTHORIZATION, TOKEN)
.contentType(APPLICATION_JSON)
.content(emailDtoRequest))
.andDo(document("certification-sendVerificationCode",
resourceDetails().tag("회사 인증").description("회사 이메일 인증을 위한 메일 전송"),
preprocessRequest(prettyPrint()),
preprocessResponse(prettyPrint()),
requestHeaders(
headerWithName(AUTHORIZATION).description("토큰")
),
requestFields(
fieldWithPath("companyEmail").description("회사 이메일")
)
)
)
.andExpect(status().isOk());
}

@Test
void verifyEmailTest() throws Exception {
String verificationCodeDtoRequest = objectMapper.writeValueAsString(
verificationCodeDtoRequest());

mockMvc.perform(post("/api/v1/certification/users/me/company-mail/verification")
.header(AUTHORIZATION, TOKEN)
.contentType(APPLICATION_JSON)
.content(verificationCodeDtoRequest))
.andDo(document("certification-verifyEmail",
resourceDetails().tag("회사 인증").description("회사 이메일 인증을 위한 코드 검증"),
preprocessRequest(prettyPrint()),
preprocessResponse(prettyPrint()),
requestHeaders(
headerWithName(AUTHORIZATION).description("토큰")
),
requestFields(
fieldWithPath("verificationCode").description("인증 코드")
)
)
)
.andExpect(status().isOk());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ void setUp() {
}

@Test
void findCertificationByUserIdTest() {
void findByUserIdTest() {
// given
Certification certification = certification(user);
certificationRepository.save(certification);
Expand Down
Loading