[spring/test]Service 테스트 / mockito

kongta2·2023년 12월 5일

mockito를 이용한 TodoService 테스트

TodoServiceTest - 테스트할 기능 구현

@ExtendWith(MockitoExtension.class)
class TodoServiceTest implements TodoTest {

    @InjectMocks
    TodoService todoService;

    @Mock
    TodoRepository todoRepository;

    @DisplayName("할일 생성")
    @Test
    void createTodo() {
        // given
        var testTodo = TodoTestUtils.get(TEST_TODO, TEST_USER);
        given(todoRepository.save(any(Todo.class))).willReturn(testTodo);

        // when
        var result = todoService.createTodo(TEST_TODO_REQUEST_DTO, TEST_USER);

        // then
        var expect = new TodoResponseDto(testTodo);
        assertThat(result).isEqualTo(expect);
    }

    @DisplayName("할일 DTO 조회")
    @Test
    void getTodoDto() {
        // given
        var testTodo = TodoTestUtils.get(TEST_TODO, TEST_USER);
        given(todoRepository.findById(eq(TEST_TODO_ID))).willReturn(Optional.of(testTodo));

        // when
        var result = todoService.getTodoDto(TEST_TODO_ID);

        // then
        assertThat(result).isEqualTo(new TodoResponseDto(testTodo));
        // isEqualTo : 주소값을 기준으로 비교
        // 필드값을 비교하기 위해서 TodoResponseDto에서 @EqualsAndHashCode(callSuper = false)
        // @EqualsAndHashCode : Equals에 HashCode를 기준으로 비교
        // Hash코드는 어노테이션을 통해 HashCode메서드가 자동으로 생성되는데 그 메서드는 필드값을 변환한 것
        // 주소값 상관없이 필드값만 같으면 같은 HashCode가 나옴
        // 같은 TEST_TODO_ID를 사용했기때문에 true
    }

    @DisplayName("할일 리스트 맵 (최신순 정렬)")
    @Test
    void getUserTodoMap() {
        // given
        var testTodo1 = TodoTestUtils.get(TEST_TODO, 1L, LocalDateTime.now(), TEST_USER);
        var testTodo2 = TodoTestUtils.get(TEST_TODO, 2L, LocalDateTime.now().minusMinutes(1), TEST_USER);
        var testAnotherTodo = TodoTestUtils.get(TEST_TODO, 1L, LocalDateTime.now(), TEST_ANOTHER_USER);

        given(todoRepository.findAll(any(Sort.class))).willReturn(List.of(testTodo1, testTodo2, testAnotherTodo));

        // when
        var result = todoService.getUserTodoMap();

        // then
        assertThat(result.get(new UserDto(TEST_USER)).get(0)).isEqualTo(new TodoResponseDto(testTodo1));
        assertThat(result.get(new UserDto(TEST_USER)).get(1)).isEqualTo(new TodoResponseDto(testTodo2));
        assertThat(result.get(new UserDto(TEST_ANOTHER_USER)).get(0)).isEqualTo(new TodoResponseDto(testAnotherTodo));
    }

    @DisplayName("할일 수정")
    @Test
    void updateTodo() {
        // given
        ReflectionTestUtils.setField(TEST_USER, User.class, "id", TEST_USER_ID, Long.class);
        var testTodo = TodoTestUtils.get(TEST_TODO, TEST_USER);
        given(todoRepository.findById(eq(TEST_TODO_ID))).willReturn(Optional.of(testTodo));

        // when
        var request = new TodoRequestDto("updateTitle", "updateContent");
        var result = todoService.updateTodo(TEST_TODO_ID, request, TEST_USER);

        // then
        assertThat(result).isEqualTo(new TodoResponseDto(testTodo));
    }

    @DisplayName("할일 완료 처리")
    @Test
    void competeTodo() {
        // given
        // id 설정
        ReflectionTestUtils.setField(TEST_USER, User.class, "id", TEST_USER_ID, Long.class);
        var testTodo = TodoTestUtils.get(TEST_TODO, TEST_USER);
        given(todoRepository.findById(eq(TEST_TODO_ID))).willReturn(Optional.of(testTodo));

        // when
        var result = todoService.completeTodo(TEST_TODO_ID, TEST_USER);

        // then
        assertThat(result.getIsCompleted()).isEqualTo(true);
    }

    @DisplayName("할일 조회")
    @Test
    void getTodo() {
        // given
        var testTodo = TodoTestUtils.get(TEST_TODO, TEST_USER);
        given(todoRepository.findById(eq(TEST_TODO_ID))).willReturn(Optional.of(testTodo));

        // when
        var result = todoService.getTodo(TEST_TODO_ID);

        // then
        assertThat(result).isEqualTo(testTodo);
    }

    @DisplayName("유저의 할일 조회")
    @Nested
    class getUserTodo {
        @DisplayName("유저의 할일 조회 성공")
        @Test
        void getUserTodo_success() {
            // given
            ReflectionTestUtils.setField(TEST_USER, User.class, "id", TEST_USER_ID, Long.class);
            var testTodo = TodoTestUtils.get(TEST_TODO, TEST_USER);
            given(todoRepository.findById(eq(TEST_TODO_ID))).willReturn(Optional.of(testTodo));

            // when
            var result = todoService.getUserTodo(TEST_TODO_ID, TEST_USER);

            // then
            assertThat(result).isEqualTo(testTodo);
        }

        @DisplayName("유저의 할일 조회 실패 - 조회 권한 없음")
        @Test
        void getUserTodo_fail() {
            // given
            ReflectionTestUtils.setField(TEST_USER, User.class, "id", TEST_USER_ID, Long.class);
            var testTodo = TodoTestUtils.get(TEST_TODO, TEST_USER);
            given(todoRepository.findById(eq(TEST_TODO_ID))).willReturn(Optional.of(testTodo));
            ReflectionTestUtils.setField(TEST_ANOTHER_USER, User.class, "id", TEST_ANOTHER_USER_ID, Long.class);

            // when & exception
            assertThrows(RejectedExecutionException.class, () -> todoService.getUserTodo(TEST_TODO_ID, TEST_ANOTHER_USER));
        }
    }
}

@ExtendWith()를 통해 단위 테스트에 사용할 확장 기능을 선언하고 MockitoExtension.class를 통해 Spring Test Context 프레임워크와 Junit5와 통합해서 사용한다.

@Mock : Mock 객체를 생성

@InjectMocks : @Mock으로 생성된 객체를 자동으로 주입

profile
2025.04.01~

0개의 댓글