Skip to content

Commit

Permalink
Feat [#22] 필터 검색에 대한 테스트 코드 구현
Browse files Browse the repository at this point in the history
1. testFindFilteredPositionsByKeyword: 유효한 키워드와 카테고리 ID가 제공될 때 메서드가 정확하게 포지션을 반환하는지 검증합니다. 이 테스트는 키워드 "1"로 검색했을 때 "[토스 뱅크] System Engineer" 포지션이 올바르게 가져오는지 확인합니다.

2. testFindPositionsByKeyword_Failure: 제공된 키워드와 카테고리 ID에 맞는 포지션이 발견되지 않을 때 RuntimeException이 발생하도록 보장합니다. 이 테스트는 검색 결과가 없는 경우를 적절히 처리하고 오류 메시지 "[ERROR] 채용 공고 검색에 실패하였습니다."가 반환되는지 검증합니다.
  • Loading branch information
jsoonworld committed May 24, 2024
1 parent e663d06 commit 8feb7a0
Showing 1 changed file with 96 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,22 @@
import org.sopt.jumpit.position.domain.Position;
import org.sopt.jumpit.position.dto.PositionsFindResponse;
import org.sopt.jumpit.position.repository.PositionRepository;
import org.sopt.jumpit.relationship.domain.PositionCategory;
import org.sopt.jumpit.relationship.service.PositionCategoryService;
import org.sopt.jumpit.skill.domain.Skill;
import org.sopt.jumpit.skill.service.SkillService;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.when;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
public class PositionServiceTest {
Expand All @@ -39,15 +44,18 @@ public class PositionServiceTest {
@Mock
private Company mockCompany;

@Mock
private PositionCategoryService positionCategoryService;

@Test
@DisplayName("키워드 '백엔드 개발자'로 검색할 때 포지션 찾기: 성공 시 결과가 포함된 리스트 반환")
@DisplayName("키워드 '백엔드 개발자'로 검색 시, 해당 키워드를 포함하는 포지션 리스트 반환")
void testFindPositionsByKeyword_Success() throws NoSuchFieldException, IllegalAccessException {
// Given: "백엔드 개발자" 키워드로 포지션을 찾기 위한 설정
Position samplePosition = createPositionWithReflection(1L, "백엔드 개발자", mockCompany);
Position samplePosition = createPositionByKeywordWithReflection(1L, "백엔드 개발자", mockCompany);
when(positionRepository.findPositionsByTitleContaining("백엔드 개발자"))
.thenReturn(Optional.of(List.of(samplePosition)));

Skill javaSkill = createSkillWithReflection("Java", "java.png");
Skill javaSkill = createSkillByKeywordWithReflection("Java", "https://drive.google.com/file/d/1TliH1yADLU_2pmpy6PjavnkqWjdJ9MGa/view?usp=drive_link");
when(skillService.findByOwnerId(anyLong()))
.thenReturn(List.of(javaSkill)); // 스킬 리스트를 반환하는 설정

Expand All @@ -59,21 +67,8 @@ void testFindPositionsByKeyword_Success() throws NoSuchFieldException, IllegalAc
assertThat(result.position().get(0).title()).isEqualTo("백엔드 개발자");
}

@Test
@DisplayName("키워드 '채은아 생일 축하해'로 검색할 때 포지션 없음: 예외 발생하여 테스트 성공")
void testFindPositionsByKeyword_NotFound() {
// Given: "Nonexistent" 키워드로 포지션을 찾지 못할 때의 설정
when(positionRepository.findPositionsByTitleContaining("채은아 생일 축하해"))
.thenReturn(Optional.empty());

// Then: 예외가 발생하면 테스트 성공으로 간주
assertThatThrownBy(() -> positionService.findPositionsByKeyword("채은아 생일 축하해"))
.isInstanceOf(NotFoundException.class)
.hasMessageContaining(ErrorMessage.SEARCH_FAILED.getMessage());
}

// 리플렉션을 사용하여 Position 객체 생성
private Position createPositionWithReflection(Long id, String title, Company company) throws NoSuchFieldException, IllegalAccessException {
private Position createPositionByKeywordWithReflection(Long id, String title, Company company) throws NoSuchFieldException, IllegalAccessException {
Position position = new Position();
Field idField = position.getClass().getDeclaredField("id");
idField.setAccessible(true);
Expand All @@ -91,7 +86,7 @@ private Position createPositionWithReflection(Long id, String title, Company com
}

// 리플렉션을 사용하여 Skill 객체 생성
private Skill createSkillWithReflection(String name, String image) throws NoSuchFieldException, IllegalAccessException {
private Skill createSkillByKeywordWithReflection(String name, String image) throws NoSuchFieldException, IllegalAccessException {
Skill skill = new Skill();
Field nameField = skill.getClass().getDeclaredField("name");
nameField.setAccessible(true);
Expand All @@ -103,4 +98,86 @@ private Skill createSkillWithReflection(String name, String image) throws NoSuch

return skill;
}

@Test
@DisplayName("존재하지 않는 키워드로 검색 시, NotFoundException 발생")
void testFindPositionsByKeyword_NotFound() {
// Given: "Nonexistent" 키워드로 포지션을 찾지 못할 때의 설정
when(positionRepository.findPositionsByTitleContaining("채은아 생일 축하해"))
.thenReturn(Optional.empty());

// Then: 예외가 발생하면 테스트 성공으로 간주
assertThatThrownBy(() -> positionService.findPositionsByKeyword("채은아 생일 축하해"))
.isInstanceOf(NotFoundException.class)
.hasMessageContaining(ErrorMessage.SEARCH_FAILED.getMessage());
}

@Test
@DisplayName("키워드와 카테고리에 따라 필터링된 포지션 목록 조회")
void testFindFilteredPositionsByKeyword() {
// Given: "1" 키워드와 카테고리 ID 목록을 설정하여 포지션 필터링을 위한 준비
// "1" 키워드로 포지션을 검색할 때 사용될 예상 키워드와 카테고리 목록을 설정
String keyword = "1";
List<Long> categoryIds = Arrays.asList(1L, 2L);

// Position 객체를 목킹하여, "[토스 뱅크] System Engineer"라는 제목과 함께 설정
Position position1 = mock(Position.class);
when(position1.getId()).thenReturn(1L);
when(position1.getTitle()).thenReturn("[토스 뱅크] System Engineer");

// Company 객체도 목킹하여, 해당 포지션의 회사 정보 반환 설정
Company mockCompany = mock(Company.class);
when(mockCompany.getId()).thenReturn(10L);
when(position1.getCompany()).thenReturn(mockCompany);

// Skill 객체를 목킹하여, "Java"라는 기술 스택 정보 반환 설정
Skill skill = mock(Skill.class);
when(skill.getName()).thenReturn("Java");
when(skill.getImage()).thenReturn("https://drive.google.com/file/d/1TliH1yADLU_2pmpy6PjavnkqWjdJ9MGa/view?usp=drive_link");

// PositionCategoryService에서 카테고리 ID에 따라 PositionCategory 객체 목 리스트를 반환하도록 설정
PositionCategory positionCategoryMock = mock(PositionCategory.class);
when(positionCategoryMock.getPosition()).thenReturn(position1);
when(positionCategoryService.findPositionByCategory(anyLong())).thenReturn(Arrays.asList(positionCategoryMock));

// PositionRepository에서 제공된 키워드를 포함하는 포지션 목록을 반환하도록 설정
when(positionRepository.findPositionsByTitleContaining(anyString())).thenReturn(Optional.of(List.of(position1)));
when(skillService.findByOwnerId(anyLong())).thenReturn(List.of(skill));

// When: 실제 검색 메서드를 실행하여 결과를 받음
PositionsFindResponse result = positionService.findFilteredPositionsByKeyword(keyword, categoryIds);

// Then: 결과 검증, "[토스 뱅크] System Engineer" 포지션을 정확하게 반환했는지 확인
assertThat(result.position()).hasSize(1);
assertThat(result.position().get(0).title()).isEqualTo("[토스 뱅크] System Engineer");

// Verify: 각 서비스의 메서드가 예상대로 호출되었는지 검증
verify(positionCategoryService, times(categoryIds.size())).findPositionByCategory(anyLong());
verify(positionRepository).findPositionsByTitleContaining(keyword.trim());
verify(skillService).findByOwnerId(position1.getId());
}

@Test
@DisplayName("키워드와 카테고리로 포지션을 찾지 못했을 때 예외를 발생시키는 실패 테스트")
void testFindPositionsByKeyword_Failure() {
// Given: "1" 키워드와 ID 1, 2로 구성된 카테고리 목록으로 설정
String keyword = "1";
List<Long> categoryIds = Arrays.asList(1L, 2L);

// PositionRepository에서 해당 키워드를 포함하는 포지션 목록이 없는 상황 설정 (빈 Optional 반환)
when(positionRepository.findPositionsByTitleContaining(keyword)).thenReturn(Optional.empty());

// When: 해당 키워드로 포지션 검색을 시도하고 결과가 없을 경우 RuntimeException을 예상
RuntimeException exception = assertThrows(RuntimeException.class, () -> {
positionService.findFilteredPositionsByKeyword(keyword, categoryIds);
});

// Then: 예외 발생을 확인하고, "포지션을 찾을 수 없습니다" 메시지가 포함되어 있는지 검증
assertThat(exception.getMessage()).contains("[ERROR] 채용 공고 검색에 실패하였습니다.");

// Verify: PositionRepository의 findPositionsByTitleContaining 메서드가 호출됨을 확인
verify(positionRepository).findPositionsByTitleContaining(keyword.trim());
verifyNoInteractions(skillService); // 검색 결과가 없으므로 SkillService는 호출되지 않음
}

}

0 comments on commit 8feb7a0

Please sign in to comment.