From c6dc0ef798ffb1e75c3d3074f03bf9eacf0aadd3 Mon Sep 17 00:00:00 2001 From: thezz9 Date: Fri, 20 Jun 2025 14:29:03 +0900 Subject: [PATCH 1/2] =?UTF-8?q?test=20:=20LanguageService,=20LanguageDomai?= =?UTF-8?q?nService=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../language/service/LanguageServiceTest.java | 219 ++++++++++++++++++ .../service/LanguageDomainServiceTest.java | 208 +++++++++++++++++ 2 files changed, 427 insertions(+) create mode 100644 src/test/java/org/ezcode/codetest/application/language/service/LanguageServiceTest.java create mode 100644 src/test/java/org/ezcode/codetest/domain/language/service/LanguageDomainServiceTest.java diff --git a/src/test/java/org/ezcode/codetest/application/language/service/LanguageServiceTest.java b/src/test/java/org/ezcode/codetest/application/language/service/LanguageServiceTest.java new file mode 100644 index 00000000..d40e4680 --- /dev/null +++ b/src/test/java/org/ezcode/codetest/application/language/service/LanguageServiceTest.java @@ -0,0 +1,219 @@ +package org.ezcode.codetest.application.language.service; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.BDDMockito.*; + +import java.util.List; + +import org.ezcode.codetest.application.submission.dto.request.language.LanguageCreateRequest; +import org.ezcode.codetest.application.submission.dto.request.language.LanguageUpdateRequest; +import org.ezcode.codetest.application.submission.dto.response.language.LanguageResponse; +import org.ezcode.codetest.application.submission.service.LanguageService; +import org.ezcode.codetest.domain.language.exception.LanguageException; +import org.ezcode.codetest.domain.language.exception.code.LanguageExceptionCode; +import org.ezcode.codetest.domain.language.model.entity.Language; +import org.ezcode.codetest.domain.language.service.LanguageDomainService; +import org.junit.jupiter.api.BeforeEach; +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; +import org.springframework.test.util.ReflectionTestUtils; + +@ExtendWith(MockitoExtension.class) +@DisplayName("언어 서비스 테스트") +public class LanguageServiceTest { + + @InjectMocks + private LanguageService languageService; + + @Mock + private LanguageDomainService languageDomainService; + + private Long languageId; + private Language language; + private LanguageCreateRequest createRequest; + private LanguageUpdateRequest updateRequest; + + @BeforeEach + void setUp() { + languageId = 1L; + + language = new Language("Java", "17", 62L); + ReflectionTestUtils.setField(language, "id", 1L); + + createRequest = new LanguageCreateRequest("Java", "17", 62L); + updateRequest = new LanguageUpdateRequest(100L); + } + + @Nested + @DisplayName("언어 서비스 성공 테스트") + class LanguageServiceSuccessTest { + + @Test + @DisplayName("언어 생성 성공") + void createLanguage() { + + // given + willDoNothing().given(languageDomainService) + .validateLanguageNotDuplicated(createRequest.name(), createRequest.version()); + + given(languageDomainService.createLanguage(any(Language.class))) + .willReturn(language); + + // when + LanguageResponse response = languageService.createLanguage(createRequest); + + // then + assertAll( + () -> assertThat(response.id()).isEqualTo(language.getId()), + () -> assertThat(response.name()).isEqualTo(language.getName()), + () -> assertThat(response.version()).isEqualTo(language.getVersion()), + () -> assertThat(response.judge0Id()).isEqualTo(language.getJudge0Id()) + ); + + then(languageDomainService).should(times(1)) + .validateLanguageNotDuplicated(createRequest.name(), createRequest.version()); + then(languageDomainService).should(times(1)).createLanguage(any(Language.class)); + } + + @Test + @DisplayName("언어 조회 성공") + void getLanguages() { + + // given + given(languageDomainService.getLanguages()).willReturn(List.of(language)); + + // when + List responses = languageService.getLanguages(); + + // then + LanguageResponse response = responses.get(0); + + assertAll( + () -> assertThat(responses).hasSize(1), + () -> assertThat(response.id()).isEqualTo(language.getId()), + () -> assertThat(response.name()).isEqualTo(language.getName()), + () -> assertThat(response.version()).isEqualTo(language.getVersion()), + () -> assertThat(response.judge0Id()).isEqualTo(language.getJudge0Id()) + ); + + then(languageDomainService).should(times(1)).getLanguages(); + } + + @Test + @DisplayName("언어 수정 성공") + void modifyLanguage() { + + // given + Long newJudge0Id = updateRequest.judge0Id(); + + given(languageDomainService.getLanguage(languageId)).willReturn(language); + willAnswer(invocationOnMock -> { + Language langArg = invocationOnMock.getArgument(0); + Long idArg = invocationOnMock.getArgument(1); + ReflectionTestUtils.setField(langArg, "judge0Id", idArg); + return null; + }).given(languageDomainService).modifyLanguage(language, newJudge0Id); + + // when + LanguageResponse response = languageService.modifyLanguage(languageId, updateRequest); + + // then + assertAll( + () -> assertThat(response.id()).isEqualTo(language.getId()), + () -> assertThat(response.name()).isEqualTo(language.getName()), + () -> assertThat(response.version()).isEqualTo(language.getVersion()), + () -> assertThat(response.judge0Id()).isEqualTo(newJudge0Id) + ); + + then(languageDomainService).should(times(1)).getLanguage(languageId); + then(languageDomainService).should(times(1)).modifyLanguage(language, newJudge0Id); + } + + @Test + @DisplayName("언어 삭제 성공") + void removeLanguage() { + + // given + willDoNothing().given(languageDomainService).validateLanguageExists(languageId); + willDoNothing().given(languageDomainService).removeLanguage(languageId); + + // when + languageService.removeLanguage(languageId); + + // then + then(languageDomainService).should(times(1)).validateLanguageExists(languageId); + then(languageDomainService).should(times(1)).removeLanguage(languageId); + } + } + + @Nested + @DisplayName("언어 서비스 실패 테스트") + class LanguageServiceFailureTest { + + @Test + @DisplayName("언어 등록: 중복 등록 시 예외 발생") + void createLanguage_Duplicate() { + + // given + String name = createRequest.name(); + String version = createRequest.version(); + + willThrow(new LanguageException(LanguageExceptionCode.LANGUAGE_ALREADY_EXISTS)) + .given(languageDomainService) + .validateLanguageNotDuplicated(name, version); + + // when & then + assertThatThrownBy(() -> languageService.createLanguage(createRequest)) + .isInstanceOf(LanguageException.class) + .hasMessage(LanguageExceptionCode.LANGUAGE_ALREADY_EXISTS.getMessage()); + + then(languageDomainService) + .should(times(1)).validateLanguageNotDuplicated(name, version); + then(languageDomainService).should(never()).createLanguage(any(Language.class)); + } + + @Test + @DisplayName("언어 수정: 존재하지 않으면 예외 발생") + void modifyLanguage_NotFound() { + + // given + + willThrow(new LanguageException(LanguageExceptionCode.LANGUAGE_NOT_FOUND)) + .given(languageDomainService) + .getLanguage(languageId); + + // when & then + assertThatThrownBy(() -> languageService.modifyLanguage(languageId, updateRequest)) + .isInstanceOf(LanguageException.class) + .hasMessage(LanguageExceptionCode.LANGUAGE_NOT_FOUND.getMessage()); + + then(languageDomainService).should(times(1)).getLanguage(languageId); + then(languageDomainService).should(never()).modifyLanguage(any(Language.class), any(Long.class)); + } + + @Test + @DisplayName("언어 삭제: 존재하지 않으면 예외 발생") + void removeLanguage_NotFound() { + + // given + + willThrow(new LanguageException(LanguageExceptionCode.LANGUAGE_NOT_FOUND)) + .given(languageDomainService) + .validateLanguageExists(languageId); + + // when & then + assertThatThrownBy(() -> languageService.removeLanguage(languageId)) + .isInstanceOf(LanguageException.class) + .hasMessage(LanguageExceptionCode.LANGUAGE_NOT_FOUND.getMessage()); + + then(languageDomainService).should(times(1)).validateLanguageExists(languageId); + then(languageDomainService).should(never()).removeLanguage(languageId); + } + } +} diff --git a/src/test/java/org/ezcode/codetest/domain/language/service/LanguageDomainServiceTest.java b/src/test/java/org/ezcode/codetest/domain/language/service/LanguageDomainServiceTest.java new file mode 100644 index 00000000..c372b166 --- /dev/null +++ b/src/test/java/org/ezcode/codetest/domain/language/service/LanguageDomainServiceTest.java @@ -0,0 +1,208 @@ +package org.ezcode.codetest.domain.language.service; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.BDDMockito.*; + +import java.util.List; +import java.util.Optional; + +import org.ezcode.codetest.domain.language.exception.LanguageException; +import org.ezcode.codetest.domain.language.exception.code.LanguageExceptionCode; +import org.ezcode.codetest.domain.language.model.entity.Language; +import org.ezcode.codetest.domain.language.repository.LanguageRepository; +import org.junit.jupiter.api.BeforeEach; +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; +import org.springframework.test.util.ReflectionTestUtils; + +@ExtendWith(MockitoExtension.class) +@DisplayName("언어 도메인 서비스 테스트") +public class LanguageDomainServiceTest { + + @InjectMocks + private LanguageDomainService languageDomainService; + + @Mock + private LanguageRepository languageRepository; + + private Long languageId; + private String name; + private String version; + private Language language; + + @BeforeEach + void setup() { + languageId = 1L; + name = "Java"; + version = "17"; + + language = new Language("Java", "17", 62L); + ReflectionTestUtils.setField(language, "id", 1L); + } + + @Nested + @DisplayName("언어 도메인 서비스 성공 테스트") + class LanguageDomainServiceSuccessTest { + + @Test + @DisplayName("존재할 때 예외 없이 통과") + void validateLanguageExists() { + + // given + given(languageRepository.existsById(languageId)).willReturn(true); + + // when & then + assertThatCode(() -> languageDomainService.validateLanguageExists(languageId)) + .doesNotThrowAnyException(); + + then(languageRepository).should(times(1)).existsById(languageId); + + } + + @Test + @DisplayName("중복 아닐 때 예외 없이 통과") + void validateLanguageNotDuplicated() { + + // given + given(languageRepository.existsByNameAndVersion(name, version)).willReturn(false); + + // when & then + assertThatCode(() -> languageDomainService.validateLanguageNotDuplicated(name, version)) + .doesNotThrowAnyException(); + + then(languageRepository).should(times(1)).existsByNameAndVersion(name, version); + } + + @Test + @DisplayName("저장한 엔티티를 그대로 반환") + void createLanguage() { + + // given + given(languageRepository.saveLanguage(language)).willReturn(language); + + // when + Language result = languageDomainService.createLanguage(language); + + // then + assertThat(result).isSameAs(language); + + then(languageRepository).should(times(1)).saveLanguage(language); + } + + @Test + @DisplayName("존재하면 엔티티 반환") + void getLanguage() { + + // given + given(languageRepository.findLanguageById(languageId)).willReturn(Optional.of(language)); + + // when + Language result = languageDomainService.getLanguage(languageId); + + // then + assertThat(result).isSameAs(language); + + then(languageRepository).should(times(1)).findLanguageById(languageId); + } + + @Test + @DisplayName("리스트 반환") + void getLanguages() { + + // given + given(languageRepository.findLanguages()).willReturn(List.of(language)); + + // when + List result = languageDomainService.getLanguages(); + + // then + assertThat(result).containsExactly(language); + then(languageRepository).should(times(1)).findLanguages(); + } + + @Test + @DisplayName("수정 메서드 호출") + void modifyLanguage() { + + // given + Long newJudge0Id = 100L; + willDoNothing().given(languageRepository).updateLanguage(language, newJudge0Id); + + // when + languageDomainService.modifyLanguage(language, newJudge0Id); + + // then + then(languageRepository).should(times(1)).updateLanguage(language, newJudge0Id); + } + + @Test + @DisplayName("삭제 메서드 호출") + void removeLanguage() { + + // given + willDoNothing().given(languageRepository).deleteLanguage(languageId); + + // when + languageDomainService.removeLanguage(languageId); + + // then + then(languageRepository).should(times(1)).deleteLanguage(languageId); + } + + } + + @Nested + @DisplayName("언어 도메인 서비스 실패 테스트") + class LanguageDomainServiceFailureTest { + + @Test + @DisplayName("존재하지 않을 때 예외 발생_1") + void validateLanguageExists_NotFound() { + + // given + given(languageRepository.existsById(languageId)).willReturn(false); + + // when & then + assertThatThrownBy(() -> languageDomainService.validateLanguageExists(languageId)) + .isInstanceOf(LanguageException.class) + .hasMessage(LanguageExceptionCode.LANGUAGE_NOT_FOUND.getMessage()); + + then(languageRepository).should(times(1)).existsById(languageId); + } + + @Test + @DisplayName("중복일 때 예외 발생") + void validateLanguageNotDuplicated_LanguageAlreadyExists() { + + // given + given(languageRepository.existsByNameAndVersion(name, version)).willReturn(true); + + // when & then + assertThatThrownBy(() -> languageDomainService.validateLanguageNotDuplicated(name, version)) + .isInstanceOf(LanguageException.class) + .hasMessage(LanguageExceptionCode.LANGUAGE_ALREADY_EXISTS.getMessage()); + + then(languageRepository).should(times(1)).existsByNameAndVersion(name, version); + } + + @Test + @DisplayName("존재하지 않을 때 예외 발생_2") + void getLanguage_NotFound() { + + // given + given(languageRepository.findLanguageById(languageId)).willReturn(Optional.empty()); + + // when + assertThatThrownBy(() -> languageDomainService.getLanguage(languageId)) + .isInstanceOf(LanguageException.class) + .hasMessage(LanguageExceptionCode.LANGUAGE_NOT_FOUND.getMessage()); + + then(languageRepository).should(times(1)).findLanguageById(languageId); + } + } +} From 137a0f689814bf026e3a8de18bd583de2d2bf224 Mon Sep 17 00:00:00 2001 From: Taeik Kim Date: Fri, 20 Jun 2025 14:30:43 +0900 Subject: [PATCH 2/2] Update LanguageDomainServiceTest.java --- .../domain/language/service/LanguageDomainServiceTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/ezcode/codetest/domain/language/service/LanguageDomainServiceTest.java b/src/test/java/org/ezcode/codetest/domain/language/service/LanguageDomainServiceTest.java index c372b166..c3a3ed88 100644 --- a/src/test/java/org/ezcode/codetest/domain/language/service/LanguageDomainServiceTest.java +++ b/src/test/java/org/ezcode/codetest/domain/language/service/LanguageDomainServiceTest.java @@ -197,7 +197,7 @@ void getLanguage_NotFound() { // given given(languageRepository.findLanguageById(languageId)).willReturn(Optional.empty()); - // when + // when & then assertThatThrownBy(() -> languageDomainService.getLanguage(languageId)) .isInstanceOf(LanguageException.class) .hasMessage(LanguageExceptionCode.LANGUAGE_NOT_FOUND.getMessage());