User Test

yeezze·2022년 7월 5일
0

TDD 연습

목록 보기
3/3

출처

TDD에서 작성 순서는 의존성이 적은 Repository, Service, Controller 순으로 작성하는 것이 좋다.
Mockito를 활용하면 원하는 결과를 stub하여 단위테스트를 진행할 수 있다.

RepositoryTest

@DataJpaTest
스프링부트는 JPA Repository를 손쉽게 테스트할 수 있는 어노테이션을 제공하고 있다. 인메모리 DB인 H2를 기반으로 테스트용 DB를 구축하며, 테스트가 끝나면 트랜잭션 롤백을 해준다. Repository 계층은 실제 DB와 통신 없이 단순 모킹하는 것은 의미가 없으므로 직접 DB와 통신하는 @DataJpaTeset를 사용한다.

혼자 의문이 드는 점은 어짜피 JPA Repository로 구현하면 메소드는 알아서 구현이 될텐데 테스트를 하는 의미가 있나? 하는 생각이 들었지만 뭐든 확실하게 하는게 좋겠지?

ServiceTest

@ExtendWith(MockitoExtension.class)
JUnit과 Mockito를 결합해주는 어노테이션

@Mock
가짜 객체를 만들어 반환해주는 어노테이션

@Stub
Stub하지 않은 메소드들은 원본 메소드 그대로 사용하는 어노테이션

@InjectMocks
Mock 또는 Spy로 생성된 가짜 객체를 자동으로 주입시켜주는 어노테이션

// given
의존성이 있는 객체는 가짜 객체(Mock)를 주입하여 어떤 결과를 반환하라고 주어진 답변을 준비시켜야한다. 예를 들어 Service의 Test를 진행한다면 Repository를 Mock 객체로 생성할테니까 Repository에 대한 stub 생성

doReturn(return 객체).when(repository).repo메소드(any(매개변수.class));

Stub 메소드: doReturn(), doNothing(), doThrow()

Mockito.verify()
Mock된 객체의 특정 메소드가 호출된 횟수 검증

verify(Mock 객체, times(숫자)).메소드(any(매개변수.class));

ControllerTest

@ExtendWith(MockitoExtension.class)

controller를 테스트하기 위해서는 http 호출이 필요하다.
일반적인 방법으로는 http를 호출이 불가능하므로 스프링에서는 이를 위한 MockMvc를 제공하고 있다.

MockMvc
http 호출을 위한 라이브러리

@BeforeEach
    public void init() {
        mockMvc = MockMvcBuilders.standaloneSetup(userController).build();
    }

// when
MockMvc에 데이터와 함께 http request 호출을 해야한다. 요청 정보는 mockMvc.perform()을 활용한다. perform 안에는 MockMvcRequestBuilders가 사용되며 요청 메소드 종류, 타입, 내용을 설정할 수 있다.

ResultActions resultActions = mockMvc.perform(
	MockMvcRequestBuilders.post("url")
    	.contentType(MediaType.APPLICATION_JSON)
        .content(new Gson().toJson(request))
);

// then

then 단계에서는 http 상태코드와 응답 결과를 검증한다.

post 요청

원래 http 요청을 받으면 Spring 내부에서 Json String을 객체로 변환한다. 요청을 보낼 때는 Json으로 보내야하니까 Gson을 사용해서 request DTO 객체를 Json으로 변환해준다.

post 요청 응답 검증 시에는 jsonPath를 이용해 해당 json 값이 존재하는지 확인하면 된다.

MvcResult mvcResult = resultActions.andExpect(status().isCreated())
                .andExpect(jsonPath("email", response.getEmail()).exists())
                .andExpect(jsonPath("userIdx", response.getUserIdx()).exists())
                .andReturn();

get 요청

MvcResult mvcResult = resultActions.andExpect(status().isOk()).andReturn();

// Json -> 객체 변환
UserListResponseDTO response = new Gson().fromJson(mvcResult.getResponse().getContentAsString(), UserListResponseDTO.class);
assertThat(response.getUserList().size()).isEqualTo(5);

느낀점

블로그글을 따라서 무작정 해봤는데 아무것도 없는 상태에서 Test 코드부터 작성하는게 굉장히 생소하고 은근 어렵게 느껴졌다.
당연히 컴파일 단계에서 모든 것이 오류가 나다보니 당황스럽고 이게 맞나? 하는 기분이 들었다.
User 도메인 하나만 따라서 해봤지만 느낀 점은 TDD 형식으로 개발을 하다보면 실수가 줄어들 것 같고, 조금 더 체계적으로 생각하면서 개발하게 되는 것 같다.
시간은 좀 더 오래걸리지만.. 특히 Controller 부분은 http 요청까지 직접 작성하다보니 다소 어렵고 복잡하게 느껴졌다. Spring은 정말 다양한 기능이 방대하게 존재하는 것 같다...!

profile
백엔드 개발자 😊

0개의 댓글