diff --git a/src/main/java/com/inq/wishhair/wesharewishhair/global/mail/EmailSender.java b/src/main/java/com/inq/wishhair/wesharewishhair/global/mail/EmailSender.java index ec335cb..174e3dd 100644 --- a/src/main/java/com/inq/wishhair/wesharewishhair/global/mail/EmailSender.java +++ b/src/main/java/com/inq/wishhair/wesharewishhair/global/mail/EmailSender.java @@ -14,10 +14,8 @@ import jakarta.mail.MessagingException; import jakarta.mail.internet.InternetAddress; import jakarta.mail.internet.MimeMessage; -import lombok.RequiredArgsConstructor; @Component -@RequiredArgsConstructor public class EmailSender { private static final String AUTH_MAIL_TITLE = "We-Share-Wish-Hair 이메일 인증"; @@ -26,26 +24,53 @@ public class EmailSender { private static final String AUTH_TEMPLATE = "AuthMailTemplate"; private static final String REFUND_TEMPLATE = "RefundRequestMailTemplate"; - @Value("${spring.mail.username}") - private String from; - @Value("${mail.point-mail-receiver}") - private String receiver; + private final String from; + private final String receiver; private final JavaMailSender mailSender; private final ITemplateEngine templateEngine; - public void sendAuthMail(String address, String authKey) throws MessagingException, UnsupportedEncodingException { + public EmailSender( + @Value("${spring.mail.username}") String from, + @Value("${mail.point-mail-receiver}") String receiver, + JavaMailSender mailSender, + ITemplateEngine templateEngine + ) { + this.from = from; + this.receiver = receiver; + this.mailSender = mailSender; + this.templateEngine = templateEngine; + } + + private MimeMessage generateMessage( + String address, + String htmlTemplate, + String subject + ) throws MessagingException, UnsupportedEncodingException { + MimeMessage mimeMessage = mailSender.createMimeMessage(); + MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, "UTF-8"); + mimeMessageHelper.setTo(address); + mimeMessageHelper.setFrom(new InternetAddress(from, PERSONAL)); + mimeMessageHelper.setSubject(subject); + mimeMessageHelper.setText(htmlTemplate, true); + return mimeMessage; + } + public boolean sendAuthMail( + String address, + String authKey + ) throws MessagingException, UnsupportedEncodingException { Context context = new Context(); context.setVariable("authKey", authKey); String htmlTemplate = templateEngine.process(AUTH_TEMPLATE, context); MimeMessage mimeMessage = generateMessage(address, htmlTemplate, AUTH_MAIL_TITLE); - mailSender.send(mimeMessage); + + return true; } - public void sendRefundRequestMail(RefundMailSendEvent event) throws + public boolean sendRefundRequestMail(RefundMailSendEvent event) throws MessagingException, UnsupportedEncodingException { @@ -58,19 +83,8 @@ public void sendRefundRequestMail(RefundMailSendEvent event) throws String htmlTemplate = templateEngine.process(REFUND_TEMPLATE, context); MimeMessage mimeMessage = generateMessage(receiver, htmlTemplate, REFUND_MAIL_TITLE); - mailSender.send(mimeMessage); - } - private MimeMessage generateMessage(String address, String htmlTemplate, String subject) throws - MessagingException, - UnsupportedEncodingException { - MimeMessage mimeMessage = mailSender.createMimeMessage(); - MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, "UTF-8"); - mimeMessageHelper.setTo(address); - mimeMessageHelper.setFrom(new InternetAddress(from, PERSONAL)); - mimeMessageHelper.setSubject(subject); - mimeMessageHelper.setText(htmlTemplate, true); - return mimeMessage; + return true; } } diff --git a/src/main/java/com/inq/wishhair/wesharewishhair/hairstyle/presentation/HairStyleSearchController.java b/src/main/java/com/inq/wishhair/wesharewishhair/hairstyle/presentation/HairStyleSearchController.java index 9c2c2fa..22823c8 100644 --- a/src/main/java/com/inq/wishhair/wesharewishhair/hairstyle/presentation/HairStyleSearchController.java +++ b/src/main/java/com/inq/wishhair/wesharewishhair/hairstyle/presentation/HairStyleSearchController.java @@ -12,13 +12,11 @@ import com.inq.wishhair.wesharewishhair.global.annotation.FetchAuthInfo; import com.inq.wishhair.wesharewishhair.global.dto.response.PagedResponse; import com.inq.wishhair.wesharewishhair.global.dto.response.ResponseWrapper; -import com.inq.wishhair.wesharewishhair.global.exception.ErrorCode; -import com.inq.wishhair.wesharewishhair.global.exception.WishHairException; import com.inq.wishhair.wesharewishhair.global.resolver.dto.AuthInfo; -import com.inq.wishhair.wesharewishhair.hairstyle.domain.hashtag.Tag; import com.inq.wishhair.wesharewishhair.hairstyle.application.HairStyleSearchService; import com.inq.wishhair.wesharewishhair.hairstyle.application.dto.response.HairStyleResponse; import com.inq.wishhair.wesharewishhair.hairstyle.application.dto.response.HairStyleSimpleResponse; +import com.inq.wishhair.wesharewishhair.hairstyle.domain.hashtag.Tag; import lombok.RequiredArgsConstructor; @@ -34,8 +32,6 @@ public ResponseWrapper respondRecommendedHairStyle( @RequestParam(defaultValue = "ERROR") List tags, @FetchAuthInfo AuthInfo authInfo ) { - validateHasTag(tags); - return hairStyleSearchService.recommendHair(tags, authInfo.userId()); } @@ -58,10 +54,4 @@ public PagedResponse findWishHairStyles( public ResponseWrapper findAllHairStyles() { return hairStyleSearchService.findAllHairStyle(); } - - private void validateHasTag(List tags) { - if (tags.get(0).equals(Tag.ERROR)) { - throw new WishHairException(ErrorCode.RUN_NOT_ENOUGH_TAG); - } - } } diff --git a/src/main/java/com/inq/wishhair/wesharewishhair/photo/infrastructure/S3PhotoStore.java b/src/main/java/com/inq/wishhair/wesharewishhair/photo/infrastructure/S3PhotoStore.java index 90166ae..6412d11 100644 --- a/src/main/java/com/inq/wishhair/wesharewishhair/photo/infrastructure/S3PhotoStore.java +++ b/src/main/java/com/inq/wishhair/wesharewishhair/photo/infrastructure/S3PhotoStore.java @@ -24,6 +24,22 @@ public class S3PhotoStore implements PhotoStore { private final AmazonS3Client amazonS3Client; private final String buketName; + private void deleteFile(final String storeUrl) { + int point = storeUrl.indexOf('/', 10) + 1; + String fileKey = storeUrl.substring(point); + amazonS3Client.deleteObject(buketName, fileKey); + } + + private String createStoreFilename(final String originalFilename) { + String ext = getExt(originalFilename); + return UUID.randomUUID() + ext; + } + + private String getExt(final String originalFilename) { + int index = originalFilename.lastIndexOf("."); + return originalFilename.substring(index); + } + public S3PhotoStore(final AmazonS3Client amazonS3Client, @Value("${cloud.aws.s3.bucket}") String buketName) { this.amazonS3Client = amazonS3Client; @@ -37,8 +53,6 @@ public List uploadFiles(final List files) { } private String uploadFile(final MultipartFile file) { - validateFileExist(file); - String originalFilename = file.getOriginalFilename(); String storeFilename = createStoreFilename(originalFilename); @@ -65,26 +79,4 @@ public boolean deleteFiles(final List storeUrls) { storeUrls.forEach(this::deleteFile); return true; } - - private void deleteFile(final String storeUrl) { - int point = storeUrl.indexOf('/', 10) + 1; - String fileKey = storeUrl.substring(point); - amazonS3Client.deleteObject(buketName, fileKey); - } - - private void validateFileExist(final MultipartFile file) { - if (file == null || file.isEmpty()) { - throw new WishHairException(ErrorCode.EMPTY_FILE_EX); - } - } - - private String createStoreFilename(final String originalFilename) { - String ext = getExt(originalFilename); - return UUID.randomUUID() + ext; - } - - private String getExt(final String originalFilename) { - int index = originalFilename.lastIndexOf("."); - return originalFilename.substring(index); - } } \ No newline at end of file diff --git a/src/test/java/com/inq/wishhair/wesharewishhair/auth/presentation/MailAuthControllerTest.java b/src/test/java/com/inq/wishhair/wesharewishhair/auth/presentation/MailAuthControllerTest.java index 8045de2..e9cab23 100644 --- a/src/test/java/com/inq/wishhair/wesharewishhair/auth/presentation/MailAuthControllerTest.java +++ b/src/test/java/com/inq/wishhair/wesharewishhair/auth/presentation/MailAuthControllerTest.java @@ -5,17 +5,16 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; -import com.inq.wishhair.wesharewishhair.auth.application.MailAuthService; +import com.inq.wishhair.wesharewishhair.auth.domain.AuthCodeRepository; +import com.inq.wishhair.wesharewishhair.auth.domain.entity.AuthCode; import com.inq.wishhair.wesharewishhair.auth.presentation.dto.request.AuthKeyRequest; import com.inq.wishhair.wesharewishhair.auth.presentation.dto.request.MailRequest; import com.inq.wishhair.wesharewishhair.common.support.ApiTestSupport; -import com.inq.wishhair.wesharewishhair.user.application.utils.UserValidator; @DisplayName("[MailAuthController 테스트] - API") class MailAuthControllerTest extends ApiTestSupport { @@ -27,10 +26,8 @@ class MailAuthControllerTest extends ApiTestSupport { @Autowired private MockMvc mockMvc; - @MockBean - private UserValidator userValidator; - @MockBean - private MailAuthService mailAuthService; + @Autowired + private AuthCodeRepository authCodeRepository; @Test @DisplayName("[이메일 중복검사 API 를 호출한다]") @@ -72,7 +69,8 @@ void sendAuthorizationMail() throws Exception { @DisplayName("[인증코드 확인 API 를 호출한다]") void authorizeKey() throws Exception { //given - AuthKeyRequest authKeyRequest = new AuthKeyRequest(EMAIL, "authcode"); + authCodeRepository.save(new AuthCode(EMAIL, "1234")); + AuthKeyRequest authKeyRequest = new AuthKeyRequest(EMAIL, "1234"); //when ResultActions result = mockMvc.perform( diff --git a/src/test/java/com/inq/wishhair/wesharewishhair/global/mail/EmailSenderTest.java b/src/test/java/com/inq/wishhair/wesharewishhair/global/mail/EmailSenderTest.java new file mode 100644 index 0000000..7f4b1e7 --- /dev/null +++ b/src/test/java/com/inq/wishhair/wesharewishhair/global/mail/EmailSenderTest.java @@ -0,0 +1,68 @@ +package com.inq.wishhair.wesharewishhair.global.mail; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.BDDMockito.*; + +import java.io.UnsupportedEncodingException; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.mail.javamail.JavaMailSender; +import org.thymeleaf.ITemplateEngine; +import org.thymeleaf.context.Context; + +import com.inq.wishhair.wesharewishhair.user.event.RefundMailSendEvent; + +import jakarta.mail.MessagingException; +import jakarta.mail.internet.MimeMessage; + +@DisplayName("[EmailSender 테스트]") +class EmailSenderTest { + + private static final String AUTH_TEMPLATE = "AuthMailTemplate"; + private static final String REFUND_TEMPLATE = "RefundRequestMailTemplate"; + private static final String ADDRESS = "hello@naver.com"; + + private final EmailSender emailSender; + private final JavaMailSender mailSender; + private final ITemplateEngine templateEngine; + private final MimeMessage mimeMessage; + + public EmailSenderTest() { + this.mailSender = Mockito.mock(); + this.templateEngine = Mockito.mock(ITemplateEngine.class); + this.mimeMessage = Mockito.mock(MimeMessage.class); + this.emailSender = new EmailSender("from", "receiver", mailSender, templateEngine); + } + + @Test + @DisplayName("인증 메일 발송 테스트") + void sendAuthMail() throws MessagingException, UnsupportedEncodingException { + //given + given(templateEngine.process(any(String.class), any(Context.class))).willReturn(AUTH_TEMPLATE); + given(mailSender.createMimeMessage()).willReturn(mimeMessage); + + //when + boolean actual = emailSender.sendAuthMail(ADDRESS, "1927"); + + //then + assertThat(actual).isTrue(); + } + + @Test + @DisplayName("환급 요청 메일 발송 테스트") + void sendRefundRequestMail() throws MessagingException, UnsupportedEncodingException { + //given + given(templateEngine.process(any(String.class), any(Context.class))).willReturn(REFUND_TEMPLATE); + given(mailSender.createMimeMessage()).willReturn(mimeMessage); + RefundMailSendEvent event = new RefundMailSendEvent("userA", "기업은행", "111111111", 1000); + + //when + boolean actual = emailSender.sendRefundRequestMail(event); + + //then + assertThat(actual).isTrue(); + } +} \ No newline at end of file diff --git a/src/test/java/com/inq/wishhair/wesharewishhair/global/mail/event/MailSendEventListenerTest.java b/src/test/java/com/inq/wishhair/wesharewishhair/global/mail/event/MailSendEventListenerTest.java new file mode 100644 index 0000000..2fb3946 --- /dev/null +++ b/src/test/java/com/inq/wishhair/wesharewishhair/global/mail/event/MailSendEventListenerTest.java @@ -0,0 +1,49 @@ +package com.inq.wishhair.wesharewishhair.global.mail.event; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.BDDMockito.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; + +import com.inq.wishhair.wesharewishhair.auth.event.AuthMailSendEvent; +import com.inq.wishhair.wesharewishhair.common.support.MockTestSupport; +import com.inq.wishhair.wesharewishhair.global.mail.EmailSender; +import com.inq.wishhair.wesharewishhair.point.application.dto.PointUseRequest; +import com.inq.wishhair.wesharewishhair.user.domain.entity.Email; +import com.inq.wishhair.wesharewishhair.user.event.RefundMailSendEvent; + +class MailSendEventListenerTest extends MockTestSupport { + private static final String ADDRESS = "hello@naver.com"; + + @InjectMocks + private MailSendEventListener listener; + + @Mock + private EmailSender emailSender; + + @Test + @DisplayName("인증 메일 발송 이벤트 리스너 테스트") + void sendAuthMail() throws Exception { + //given + final String authKey = "2816"; + given(emailSender.sendAuthMail(anyString(), anyString())).willReturn(true); + + //when, then + assertDoesNotThrow(() -> listener.sendAuthMail(new AuthMailSendEvent(new Email(ADDRESS), authKey))); + } + + @Test + @DisplayName("포인트 환급요청 메일 발송 이벤트 리스너 테스트") + void sendRefundMail() throws Exception { + //given + PointUseRequest request = new PointUseRequest("bank", "1234", 1000); + RefundMailSendEvent event = request.toRefundMailEvent("userName"); + given(emailSender.sendRefundRequestMail(event)).willReturn(true); + + //when, then + assertDoesNotThrow(() -> listener.sendRefundMail(event)); + } +}