[워밍업 클럽 2기 BE 클린코드 & 테스트] Mission Day18
Practical Testing: 실용적인 테스트 가이드를 수강하고 진행한 미션입니다.
@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 등으로 생성된 객체를 주입시킴
주로 테스트 대상 클래스의 의존성을 주입할 때 사용
아래 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
검증
}
댓글을 작성해보세요.