Junit Controller 테스트 코드 작성

haaaalin·2023년 3월 23일
0

Junit

Junit

자바 프로그래밍 언어용 단위 테스트 프레임워크

Junit LifeCycle

아래는 Junit LifeCycle 어노테이션이다.

AnnotationDescription
@Test테스트용 메소드를 표현하는 어노테이션
@BeforEach각 테스트 메소드가 시작되기 전에, 실행되어야 하는 메소들 표현
@AfterEach각 테스트 메소드가 시작된 후 실행되어야 하는 메소드르 표현
@BeforeAll테스트 시작 전에 실행되어야 하는 메소드를 표현(Static 처리 필요)
@AfterAll테스트 종료 후에 실행되어야 하는 메소드를 표현(Static 처리 필요)



컨트롤러의 테스트 코드 작성법

  • MockMVC를 통해 API 호출, 해당 컨트롤러에서 의존하고 있는 객체는 Mock객체로 만들어 주입(@MockBean 사용)
  • Mock 객체는 가짜라서 리턴되는 값이 없음 → given, when 등으로 원하는 값 리턴하도록 미리 조작
  • 로직이 진행된 후 verify를 통해 검증
  • 컨트롤러는 @SpringBootTest, @WebMvcTest 어노테이션을 사용해 테스트

⭐️ @WebMvcTest vs @SpringBootTest

@SpringBootTest 는 프로젝트의 전체 컨텍스트를 로드하여 빈을 주입하기 때문에 속도가 느리고, 통합 테스트를 할 때 많이 사용한다.
필요한 빈만을 등록하여 테스트를 진행하고자 한다면 슬라이스 테스트 어노테이션인 @WebMvcTest를 사용하는 것이 효율적이다.



@MockBean & @SpyBean


MockBean

Mock: 껍데기만 있는 객체

MockBean: 기존에 사용되던 Bean의 껍데기만 가져오고 내부의 구현 부분은 모두 사용자에게 위임한 상태

→ 따라서 어떤 메소드에 어떤 값이 입력되었을 때 특정 값을 리턴하도록 개발자가 조작이 가능하다

SpyBean

Spy: 조직 전체에 퍼져있지 않고, 조직 구성원 중 1명 혹은 일부분

SpyBean: given에서 선언한 코드 외에는 전부 실체 객체의 것 사용



Controller 테스트 코드 (MVC 테스트)

@WebMvcTest(MemberController.class)
class MemberControllerUnitTest {

    @Autowired
    MockMvc mvc;

    @MockBean
    MemberService memberService;
		
		@Test
    @DisplayName("멤버 전체조회 테스트")
    void getMemberListTest() throws Exception {
        List<Member> members = new ArrayList<>();
        members.add(Member.builder().name("John").build());

        given(memberService.list()).willReturn(members);

        mvc.perform(get("/api/member"))
                .andExpect(status().isOk())
                .andExpect(content().string(containsString("John")));
    }
}

@WebMvcTest(테스트할 컨트롤러.class)

  • 해당 클래스만 실체로 로드되어 테스트 진행
  • 컨트롤러를 지정해주지 않으면, @Controlelr, @RestController, @ControllerAdvice 등 연관된 bean들이 로드

MockMvc

  • 컨트롤러의 api를 테스트하는 용도인 MockMvc 객체를 주입
  • perform(httpMethod)로 실행 → andExpect, andDo, andReturn등으로 동작을 확인하는 방식

given(memberService.list()).willReturn(members);

  • 가짜객체가 원하는 행위를 할 수 있도록 정의
  • memberService.list() 메서드를 실행시키면 반환값으로 members를 리턴해달라

andExpect(content().string(containsString("John")));

  • 리턴받은 body에 John이라는 문자열이 존재하는지를 확인
  • given을 통해 mock객체의 예상한 행위가 정상적으로 동작했는지를 확인

좋은 단위 테스트 ‼️

  • 1개의 테스트는 1개의 기능에 대해서만 테스트
  • 테스트 주체와 협력자 구분!! (주체: 테스트할 객체, 협력자: 테스트를 진행하기 위해 정의하는 가짜 객체)
  • Given, when, then으로 명확하게 작성
    • Given: 테스트를 진행할 행위를 위한 사전 준비
    • when: 테스트를 진행할 행위
    • then: 테스트를 진행한 행위에 대한 결과 검증

✏️ 참고

profile
한 걸음 한 걸음 쌓아가자😎

0개의 댓글