인프런 워밍업 클럽 BE 2기 - 클린코드 / 테스트코드 발자국 4주차
강의 출처 Practical Testing: 실용적인 테스트 가이드
학습 내용
레이어드 아키텍쳐(Layered Architecture)와 테스트 - 노션 정리
Test Double
Dummy - 아무것도 하지 않는 깡통 객체.
Fake - 단순한 형태로 동일한 기능은 수행하나, 프로덕션 초기에는 부족한 객체.
Stub - 테스트에서 요청한 것에 대해 미리 준비한 결과를 제공하는 객체. 그 외에는 응답하지 않는다.
Spy - stub이면서 호출된 내용을 기록하여 보여줄 수 있는 객체. 일부는 실제 객체처럼 동작하고 일부만 stubbing 할 수 있다.
Mock - 행위에 대한 기대를 명세하고, 그에 따라 동작하도록 만들어진 객체.
Stub / Mock 의 차이? -> Stub은 상태 검증 / Mock은 행위 검증
@Mock, @Spy, @MockBean, @SpyBean, @InjectMocks - 노션 정리
BDDMockito - Mockito를 BDD 스타일로 wrap해서 사용.
// given
Mockito.when(mailSendClient.sendEmail(anyString(), anyString(), anyString(), anyString()))
.thenReturn(true);
// BDDMockito given
BDDMockito.given(mailSendClient.sendEmail(anyString(), anyString(), anyString(), anyString()))
.willReturn(true);
Classicist VS. Mockist
진짜 객체로 테스트를 하고 필요한 경우에만 mocking해서 테스트를 하자. (Classicist)
외부 시스템의 경우 mocking 처리해서 테스트.
하나의 테스트는 하나의 주제만을 가져야 한다. 논리구조(if문, for문..) 같은 경우는 지양하는 것이 좋다. 만약 케이스 확장이 필요하다면 @ParameterizedTest 사용.
테스트 환경의 독립성 보장 - given절에서는 값 넣어줄 때 생성자, builder 사용.
테스트 간 독립성 보장 - 두 가지 이상의 테스트가 하나의 자원을 공유할 때 주의해야 한다. 공유 자원(인스턴스)의 여러 시나리오를 테스트 하고 싶을 경우? -> @DynamicTest 사용.
Test Fixture
각각의 테스트에서 given이 중복되는 경우 @BeforeEach 에 작성할 경우 주의 해야 할 점 -> 각 테스트 입장에서 알지 못해도 테스트 내용을 이해하는데 문제가 없는지 / 수정해도 모든 테스트에 영향을 주지 않는지 고려해야 한다.
data.sql 사용 지양. -> 무엇을 테스트하고 있는지 파악하기 어려울 수 있다.
테스트 클래스마다 builder를 만들어서 각자 필요한 파라미터만 사용한다. (builder class를 만들어서 한 곳에서 관리하는 것이 오히려 복잡도를 늘어나게 한다.)
Test Fixture 클렌징
deleteAll()
mapping된 테이블을 조회 후 delete 한다. 연관된 테이블을 모두 조회한 후 삭제하기 때문에 시간과 비용이 들 수 있다.
테이블의 삭제 순서를 고려해야 될 수 있다.
deleteAllInBatch()
테이블의 삭제 순서를 고려해야 한다.
여러 조건들(외래키 조건..)에 따라 삭제가 되지 않을 수 있다.
테스트 환경 통합하기
ServiceTest, RepositoryTest
@ActiveProfiles("test") @SpringBootTest public abstract class IntegrationTestSupport { @MockBean protected MailSendClient mailSendClient; }
ControllerTest
@WebMvcTest(controllers = {
OrderController.class,
ProductController.class
})
public abstract class ControllerTestSupport {
@Autowired
protected MockMvc mockMvc;
@Autowired
protected ObjectMapper objectMapper;
@MockBean
protected OrderService orderService;
@MockBean
protected ProductService productService;
}
private 메서드의 테스트는 하지 말아야 한다. 꼭 해야 된다면 따로 객체를 분리해서 테스트를 할 수 있다.
테스트에서만 필요한 메서드는 만들어도 되지만, 보수적으로 접근해야 한다.
미션
미션 1 - Layered Architecture 구조의 레이어별 특징과 테스트 작성법 -> 노션 정리
미션 2 - @Mock, @Spy, @MockBean, @SpyBean, @InjectMocks 차이점 / @BeforeEach 배치 -> 노션 정리
회고
인프런 워밍업 클럽 BE 2기 4주차라니 시간이 어떻게 흘러간지 모르겠다. 이번 주는 특히나 내가 평소 궁금했던 것들에 대한 강의여서 더 집중해서 들었던 것 같다. 바로 프로젝트에 적용 해볼 만 한 내용이 많아서 만족스러웠다. 워밍업 클럽 진도를 따라가는게 쉽지는 않았지만 지나고 보니 포기하지 않고 어떻게든 하려고 노력 했던 것이 많은 도움이 된 것 같다.
댓글을 작성해보세요.