Skip to content
New issue

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

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

Already on GitHub? # to your account

[Feat] #259 - KeyResultService 테스트 코드 작성 #260

Merged
merged 4 commits into from
Apr 1, 2024
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 @@ -162,7 +162,7 @@ public Optional<AchieveResponseDto> modifyKeyResult(final KeyResultModifyRequest
throw new BadRequestException(REQUIRED_KEY_RESULT_VALUE);
}

Log updateLog = logService.createUpdateLog(request, keyResult.getId());
Log updateLog = logService.createUpdateLog(request, keyResult);
validateLogNum(request.krTarget(), updateLog.getKeyResult().getTarget());

Optional<Log> prevLog = logRepository.findLatestLogByKeyResultId(LogState.RECORD, request.keyResultId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,7 @@ public Optional<AchieveResponseDto> createRecordLog(final Long userId, final Log
return Optional.empty();
}

public Log createUpdateLog(final KeyResultModifyRequestDto request, final Long keyResultId) {
KeyResult keyResult = keyResultRepository.findById(keyResultId)
.orElseThrow(() -> new NotFoundException(NOT_FOUND_KEY_RESULT));
public Log createUpdateLog(final KeyResultModifyRequestDto request, final KeyResult keyResult) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p5;
이미 위에서 조회했으니 이렇게 해주었으면 됐었군요 !

return logRepository.save(Log.builder()
.date(LocalDateTime.now())
.state(LogState.UPDATE)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,318 @@
package org.moonshot.keyresult.service;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
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.moonshot.common.model.Period;
import org.moonshot.exception.BadRequestException;
import org.moonshot.keyresult.dto.request.KeyResultCreateRequestDto;
import org.moonshot.keyresult.dto.request.KeyResultCreateRequestInfoDto;
import org.moonshot.keyresult.dto.request.KeyResultModifyRequestDto;
import org.moonshot.keyresult.dto.response.KRDetailResponseDto;
import org.moonshot.keyresult.model.KRState;
import org.moonshot.keyresult.model.KeyResult;
import org.moonshot.keyresult.repository.KeyResultRepository;
import org.moonshot.log.dto.response.AchieveResponseDto;
import org.moonshot.log.model.Log;
import org.moonshot.log.model.LogState;
import org.moonshot.log.repository.LogRepository;
import org.moonshot.log.service.LogService;
import org.moonshot.objective.model.Category;
import org.moonshot.objective.model.Objective;
import org.moonshot.objective.repository.ObjectiveRepository;
import org.moonshot.task.dto.request.TaskCreateRequestDto;
import org.moonshot.task.repository.TaskRepository;
import org.moonshot.task.service.TaskService;
import org.moonshot.user.model.User;

@ExtendWith(MockitoExtension.class)
class KeyResultServiceTest {

@Mock
private ObjectiveRepository objectiveRepository;
@Mock
private KeyResultRepository keyResultRepository;
@Mock
private TaskRepository taskRepository;
@Mock
private TaskService taskService;
@Mock
private LogService logService;
@Mock
private LogRepository logRepository;
@InjectMocks
private KeyResultService keyResultService;

private static User fakeUser;

@BeforeAll
static void setUp() {
Long fakeUserId = 1L;
String fakeUserNickname = "tester";
fakeUser = User.buildWithId().id(fakeUserId).nickname(fakeUserNickname).build();
}

@Test
@DisplayName("Objective와 함께 생성하는 KeyResult를 생성합니다")
void Objective와_함께_생성하는_KeyResult를_생성합니다() {
//given
Objective testObjective = Objective.builder()
.title("testObjective")
.category(Category.ECONOMY)
.content("testObjective Content")
.period(Period.of(LocalDate.now(), LocalDate.from(LocalDate.now().plusDays(30))))
.user(fakeUser)
.build();
KeyResult testKeyResult = mock(KeyResult.class);
TaskCreateRequestDto firstTaskDto = new TaskCreateRequestDto("test Task 0", 0);
TaskCreateRequestDto secondTaskDto = new TaskCreateRequestDto("test Task 1", 1);
TaskCreateRequestDto thirdTaskDto = new TaskCreateRequestDto("test Task 2", 2);
List<TaskCreateRequestDto> taskList = List.of(firstTaskDto, secondTaskDto, thirdTaskDto);
KeyResultCreateRequestInfoDto firstKeyResultDto = new KeyResultCreateRequestInfoDto(
"test KR", LocalDate.now(), LocalDate.from(LocalDate.now().plusDays(30)),
0, 500000L, "건", taskList
);
KeyResultCreateRequestInfoDto secondKeyResultDto = new KeyResultCreateRequestInfoDto(
"test KR", LocalDate.now(), LocalDate.from(LocalDate.now().plusDays(30)),
1, 500000L, "건", taskList
);
List<KeyResultCreateRequestInfoDto> testRequests = new java.util.ArrayList<>(
List.of(firstKeyResultDto, secondKeyResultDto));
testRequests.add(null);
given(keyResultRepository.save(any(KeyResult.class))).willReturn(testKeyResult);
given(testKeyResult.getId()).willReturn(1L);

//when
keyResultService.createInitKRWithObjective(testObjective, testRequests);

//then
verify(keyResultRepository, times(2)).save(any(KeyResult.class));
verify(logService, times(2)).createKRLog(any(KeyResultCreateRequestInfoDto.class), any(Long.class));
verify(taskService, times(6)).saveTask(any(KeyResult.class), any(TaskCreateRequestDto.class));
}

@Test
@DisplayName("단일 KeyResult를 생성합니다")
void 단일_KeyResult를_생성합니다() {
// given
Objective testObjective = mock(Objective.class);
User testUser = mock(User.class);
KeyResult testKeyResult = mock(KeyResult.class);
KeyResultCreateRequestDto request = new KeyResultCreateRequestDto(
1L, "test KR", LocalDate.now(),
LocalDate.from(LocalDate.now().plusDays(30)),
0, 500000L, "건");

given(objectiveRepository.findObjectiveAndUserById(1L)).willReturn(Optional.of(testObjective));
given(keyResultRepository.findAllByObjective(testObjective)).willReturn(List.of(testKeyResult));
given(testObjective.getId()).willReturn(1L);
given(testObjective.getUser()).willReturn(testUser);
given(testUser.getId()).willReturn(1L);
given(keyResultRepository.save(any(KeyResult.class))).willReturn(testKeyResult);
given(testKeyResult.getId()).willReturn(2L);

// when
keyResultService.createKeyResult(request, fakeUser.getId());

// then
verify(keyResultRepository, times(1)).bulkUpdateIdxIncrease(any(Integer.class), any(Integer.class), eq(1L), eq(-1L));
verify(logService, times(1)).createKRLog(request, 2L);
}

@Test
@DisplayName("KeyResult 생성 시 최대 보유 갯수를 넘어 예외가 발생합니다")
void KeyResult_생성_시_최대_보유_갯수를_넘어_예외가_발생합니다() {
// given
Objective testObjective = mock(Objective.class);
User testUser = mock(User.class);
List krList = mock(List.class);
KeyResultCreateRequestDto request = new KeyResultCreateRequestDto(
1L, "test KR", LocalDate.now(),
LocalDate.from(LocalDate.now().plusDays(30)),
0, 500000L, "건");

given(objectiveRepository.findObjectiveAndUserById(1L)).willReturn(Optional.of(testObjective));
given(keyResultRepository.findAllByObjective(testObjective)).willReturn(krList);
given(krList.size()).willReturn(3);
given(testObjective.getUser()).willReturn(testUser);
given(testUser.getId()).willReturn(1L);

// when, then
assertThatThrownBy(() -> keyResultService.createKeyResult(request, fakeUser.getId()))
.isInstanceOf(BadRequestException.class)
.hasMessage("허용된 Key Result 개수를 초과하였습니다");
}

@Test
@DisplayName("KeyResult 생성 시 인덱스가 0 ~ ListSize(최대 개수의 범위)를 벗어나 요청된 경우 예외가 발생합니다")
void KeyResult_생성_시_인덱스가_0_ListSize를_벗어나_요청된_경우_예외가_발생합니다() {
// given
Objective testObjective = mock(Objective.class);
User testUser = mock(User.class);
List krList = mock(List.class);
KeyResultCreateRequestDto request = new KeyResultCreateRequestDto(
1L, "test KR", LocalDate.now(),
LocalDate.from(LocalDate.now().plusDays(30)),
2, 500000L, "건");

given(objectiveRepository.findObjectiveAndUserById(1L)).willReturn(Optional.of(testObjective));
given(keyResultRepository.findAllByObjective(testObjective)).willReturn(krList);
given(krList.size()).willReturn(1);
given(testObjective.getUser()).willReturn(testUser);
given(testUser.getId()).willReturn(1L);

// when, then
assertThatThrownBy(() -> keyResultService.createKeyResult(request, fakeUser.getId()))
.isInstanceOf(BadRequestException.class)
.hasMessage("정상적이지 않은 KeyResult 위치입니다.");
}

@Test
@DisplayName("KeyResult의 데이터를 조회합니다")
void KeyResult의_데이터를_조회합니다() {
// given
Long testKeyResultId = 99L;
Objective testObjective = Objective.builder()
.title("testObjective")
.user(fakeUser).build();
KeyResult testKeyResult = KeyResult.builder()
.title("testKeyResult")
.objective(testObjective)
.target(1L)
.metric("건")
.idx(0)
.state(KRState.PROGRESS)
.period(Period.of(LocalDate.now(), LocalDate.from(LocalDate.now().plusDays(30))))
.build();
Log testLog = Log.builder().keyResult(testKeyResult).state(LogState.RECORD).currNum(10000L).build();
List<Log> logList = List.of(testLog);
given(keyResultRepository.findKeyResultAndObjective(testKeyResultId)).willReturn(Optional.of(testKeyResult));
given(logService.getLogList(testKeyResult)).willReturn(logList);
given(logService.calculateKRProgressBar(testLog, testKeyResult.getTarget())).willReturn((short) 100);

// when
KRDetailResponseDto krDetails = keyResultService.getKRDetails(fakeUser.getId(), testKeyResultId);

// then
assertThat(krDetails.target()).isEqualTo(1L);
assertThat(krDetails.metric()).isEqualTo("건");
assertThat(krDetails.progressBar()).isEqualTo((short) 100);
assertThat(krDetails.krState()).isEqualTo(KRState.PROGRESS.getValue());
assertThat(krDetails.title()).isEqualTo("testKeyResult : ");
}

@Test
@DisplayName("KeyResult의 제목 및 날짜 데이터를 수정합니다")
void KeyResult의_제목_및_날짜_데이터를_수정합니다() {
// given
Long testKeyResultId = 99L;
KeyResult testKeyResult = mock(KeyResult.class);
Objective testObjective = mock(Objective.class);
KeyResultModifyRequestDto request = new KeyResultModifyRequestDto(
testKeyResultId, "modified KeyResult Title", LocalDate.of(2024, 4, 1),
LocalDate.of(2024, 5, 1), null, null, null);
given(keyResultRepository.findKeyResultAndObjective(testKeyResultId)).willReturn(Optional.of(testKeyResult));
given(testKeyResult.getObjective()).willReturn(testObjective);
given(testKeyResult.getPeriod()).willReturn(Period.of(LocalDate.of(2023, 4, 1), LocalDate.of(2023, 5, 1)));
given(testObjective.getPeriod()).willReturn(Period.of(LocalDate.of(2023, 4, 1), LocalDate.of(2025, 5, 1)));
given(testObjective.getUser()).willReturn(fakeUser);

// when
keyResultService.modifyKeyResult(request, fakeUser.getId());

// then
verify(testKeyResult, times(1)).modifyTitle(request.krTitle());
verify(testKeyResult, times(1)).modifyPeriod(any(Period.class));
}

@Test
@DisplayName("KeyResult의 상태 데이터를 수정합니다")
void KeyResult의_상태_데이터를_수정합니다() {
// given
Long testKeyResultId = 99L;
KeyResult testKeyResult = mock(KeyResult.class);
Objective testObjective = mock(Objective.class);
KeyResultModifyRequestDto request = new KeyResultModifyRequestDto(
testKeyResultId, null, null, null, null, KRState.DONE, null);
given(keyResultRepository.findKeyResultAndObjective(testKeyResultId)).willReturn(Optional.of(testKeyResult));
given(testKeyResult.getObjective()).willReturn(testObjective);
given(testObjective.getUser()).willReturn(fakeUser);

// when
Optional<AchieveResponseDto> response = keyResultService.modifyKeyResult(request, fakeUser.getId());

// then
verify(testKeyResult, times(1)).modifyState(KRState.DONE);
assertThat(response.isEmpty()).isEqualTo(true);
}

@Test
@DisplayName("KeyResult 수정 시 목표치와 체크인 내용이 둘다 없을 경우 예외가 발생합니다")
void KeyResult_수정_시_목표치와_체크인_내용이_둘다_없을_경우_예외가_발생합니다() {
// given
Long testKeyResultId = 99L;
KeyResult testKeyResult = mock(KeyResult.class);
Objective testObjective = mock(Objective.class);
KeyResultModifyRequestDto request = new KeyResultModifyRequestDto(
testKeyResultId, null, null, null, null, null, null);
given(keyResultRepository.findKeyResultAndObjective(testKeyResultId)).willReturn(Optional.of(testKeyResult));
given(testKeyResult.getObjective()).willReturn(testObjective);
given(testObjective.getUser()).willReturn(fakeUser);

// when, then
assertThatThrownBy(() -> keyResultService.modifyKeyResult(request, fakeUser.getId()))
.isInstanceOf(BadRequestException.class)
.hasMessage("KR 수정시 목표값과 체크인 로그는 필수 입력값입니다.");
}

@Test
@DisplayName("KeyResult의 목표치를 수정하고 체크인 로그를 추가합니다")
void KeyResult의_목표치를_수정하고_체크인_로그를_추가합니다() {
// given
Long testKeyResultId = 99L;
KeyResult testKeyResult = mock(KeyResult.class);
Objective testObjective = mock(Objective.class);
Log testLog = mock(Log.class);
Log prevTestLog = mock(Log.class);
KeyResultModifyRequestDto request = new KeyResultModifyRequestDto(
testKeyResultId, null, null, null, 100000L, null, "new check-in");
given(keyResultRepository.findKeyResultAndObjective(testKeyResultId)).willReturn(Optional.of(testKeyResult));
given(testKeyResult.getObjective()).willReturn(testObjective);
given(testKeyResult.getTarget()).willReturn(1L);
doNothing().when(testKeyResult).modifyTarget(request.krTarget());

given(testObjective.getUser()).willReturn(fakeUser);
given(testLog.getKeyResult()).willReturn(testKeyResult);
given(logService.createUpdateLog(request, testKeyResult)).willReturn(testLog);
given(logRepository.findLatestLogByKeyResultId(LogState.RECORD, testKeyResultId)).willReturn(Optional.of(prevTestLog));

/* isKeyResultAchieved */
given(testObjective.getProgress()).willReturn((short) 1);

// when
Optional<AchieveResponseDto> response = keyResultService.modifyKeyResult(request, fakeUser.getId());

// then
verify(testKeyResult, times(1)).modifyProgress(any(Short.class));
verify(testObjective, times(1)).modifyProgress(any(Short.class));
assertThat(response.isEmpty()).isEqualTo(true);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ static void setUp() {
@Test
@DisplayName("Objective의 히스토리를 조회합니다")
void Objective의_히스토리를_조회합니다() {
//given
// given
Objective objective1 = Objective.builder()
.user(fakeUser)
.title("Objective 1")
Expand Down
Loading