🖤인프런만의 100% 블프 이벤트🖤

🎁100% 환급+할인+당첨 가능한 인프런 블프 구경오세요!

[워밍업 클럽 2기 BE 클린코드 & 테스트] Mission Day18

 

Practical Testing: 실용적인 테스트 가이드를 수강하고 진행한 미션입니다.

 

  1. @Mock, @MockBean, @Spy, @SpyBean, @InjectMocks 의 차이를 한번 정리해 봅시다.

  • @Mock

    • Mockito에서 제공하는 어노테이션

    • 스프링 컨텍스트 없이 단위 테스트 가능

    • 가짜 객체를 생성, 모든 메소드는 기본적으로 아무 동작도 하지 않음 -> Stubbing 필요

  • @MockBean

    • Spring Boot Test에서 제공하는 어노테이션

    • 스프링이 mock 객체를 주입 -> 주로 통합테스트에 사용

    • 스프링 빈을 mock 객체로 대체할 때 사용

  • @Spy

    • Mockito에서 제공하는 어노테이션

    • 스프링 컨텍스트 없이 단위 테스트 가능

    • 실제 객체를 사용

    • 실제 객체를 부분적으로 mock할 때 사용

    • mock하지 않은 메소드는 실제 객체의 메소드가 동작함

  • @SpyBean

    • Spring Boot Test에서 제공하는 어노테이션

    • 스프링이 spy 객체를 주입 -> 주로 통합테스트에 사용

    • 스프링 빈을 spy 객체로 대체할 때 사용 -> 실제 객체를 감싸서 일부 기능만 mock

  • @InjectMocks

    • Mockito에서 제공하는 어노테이션

    • @Mock이나 @Spy 등으로 생성된 객체를 주입시킴

    • 주로 테스트 대상 클래스의 의존성을 주입할 때 사용

 

  1. 아래 3개의 테스트가 있습니다. 내용을 살펴보고, 각 항목을 @BeforeEach, given절, when절에 배치한다면 어떻게 배치하고 싶으신가요? (@BeforeEach에 올라간 내용은 공통 항목으로 합칠 수 있습니다. ex. 1-1과 2-1을 하나로 합쳐서 @BeforeEach에 배치)

  • 요구 사항

    • 게시판 게시물에 달리는 댓글을 담당하는 Service Test

    • 댓글을 달기 위해서는 게시물과 사용자가 필요하다.

    • 게시물을 올리기 위해서는 사용자가 필요하다.

@BeforeEach 
void setUp() {
    ❓
} 

@DisplayName("사용자가 댓글을 작성할 수 있다.")
@Test
void writeComment() {
    1-1. 사용자 생성에 필요한 내용 준비
    1-2. 사용자 생성
    1-3. 게시물 생성에 필요한 내용 준비
    1-4. 게시물 생성
    1-5. 댓글 생성에 필요한 내용 준비
    1-6. 댓글 생성

    // given
    ❓

    // when
    ❓

    // then
    검증
}

@DisplayName("사용자가 댓글을 수정할 수 있다.")
@Test
void updateComment() {
    2-1. 사용자 생성에 필요한 내용 준비
    2-2. 사용자 생성
    2-3. 게시물 생성에 필요한 내용 준비
    2-4. 게시물 생성
    2-5. 댓글 생성에 필요한 내용 준비
    2-6. 댓글 생성
    2-7. 댓글 수정

    // given
    ❓

    // when
    ❓

    // then
    검증
}

@DisplayName("자신이 작성한 댓글이 아니면 수정할 수 없다.")
@Test
void cannotUpdateCommentWhenUserIsNotWriter() {
    3-1. 사용자1 생성에 필요한 내용 준비
    3-2. 사용자1 생성
    3-3. 사용자2 생성에 필요한 내용 준비
    3-4. 사용자2 생성
    3-5. 사용자1의 게시물 생성에 필요한 내용 준비
    3-6. 사용자1의 게시물 생성
    3-7. 사용자1의 댓글 생성에 필요한 내용 준비
    3-8. 사용자1의 댓글 생성
    3-9. 사용자2가 사용자1의 댓글 수정 시도

    // given
    ❓

    // when
    ❓

    // then
    검증        
}

 

  • Refactoring

    • Fixture에 부분을 최대한 보수적인 관점으로 대했다. 꼭 필요한 부분만 BeforeEach 절에 담으려고 했고, 애매한 부분은 각 테스트 내에 담았다.

    • "자신이 작성한 댓글이 아니면 수정할 수 없다." 부분이 애매하다고 느꼈다. 검증 단계에서 서로 다른 사용자라는 부분을 추출해서 보여줄 여지가 있다고 생각해 해당 테스트 내에 다 담았다. 구체적인 로직이 있으면 검증에 영향이 가지 않고, 다른 테스트에서도 공통적으로 사용되는 부분이 있으면 setUp으로 이관해도 좋다고 생각한다.

@BeforeEach 
void setUp() {
    사용자 생성에 필요한 내용 준비
    게시물 생성에 필요한 내용 준비
} 

@DisplayName("사용자가 댓글을 작성할 수 있다.")
@Test
void writeComment() {
    
    // given
    사용자 생성
    게시물 생성
    댓글 생성에 필요한 내용 준비

    // when
    댓글 생성

    // then
    검증
}

@DisplayName("사용자가 댓글을 수정할 수 있다.")
@Test
void updateComment() {

    // given
    사용자 생성
    게시물 생성
    댓글 생성에 필요한 내용 준비
    댓글 생성

    // when
    댓글 수정

    // then
    검증
}

@DisplayName("자신이 작성한 댓글이 아니면 수정할 수 없다.")
@Test
void cannotUpdateCommentWhenUserIsNotWriter() {

    // given
    사용자1 생성에 필요한 내용 준비
    사용자1 생성
    사용자2 생성에 필요한 내용 준비
    사용자2 생성
    사용자1의 게시물 생성에 필요한 내용 준비
    사용자1의 게시물 생성
    사용자1의 댓글 생성에 필요한 내용 준비
    사용자1의 댓글 생성

    // when
    사용자2가 사용자1의 댓글 수정 시도

    // then
    검증        
}

댓글을 작성해보세요.

채널톡 아이콘