Business Layer & mock

userService가 userRepository에 의존하고 있기 때문에,
userService의 테스트코드 실행 시 실제 DB와의 연동이 불가피함
=> userRepository를 가짜객체로 만들기
=> DB와의 연동이 일어나지 않아 효율적!

유저목록 조회 단위테스트

@Mock  // userRepository는 가짜 객체가 됨
private UserRepository userRepository;

@InjectMocks  // userService가 의존하는 Mock 객체인 userRepository를 주입(DI)받음
private UserService userService;

@Test
void getUsers() throws Exception {
    // given
    List<User> users = getUserList();

    // when : userRepository는 빈껍데기인 가짜객체이기 때문에 아무런 기능을 하지 않음 따라서 특정 메서드 호출에 대한 반환값 명시필요
    doReturn(users).when(userRepository).findAll(); 

    // then : userService.findUsers() 메서드는 userRepository.findAll() 메서드가 호출된 반환값을 반환, 그렇기 때문에 users가 위에서 명시한 것처럼 users 가 반환됨
    List<User> userList = userService.findUsers();

    assertThat(userList.size(), is(users.size())); // 사이즈가 같음을 확인
}



MockMVC

API의 경우 함수실행을 위해 메소드가 아닌 API가 호출됨
-> API요청을 받아 전달하기 위한 별도객체 필요
-> Spring Test에서는 이를 위해 MockMVC 지원

  • MockMVC : 애플리케이션을 서버에 배포하지 않고도 Spring 의 MVC test 가능하게 해줌
    Controller에 대한 API를 받아 넘겨줄 수 있음

MockMVC 설정

  • @ContextHierychy : 테스트용 DI container 작성 시 Bean파일 저장
@ContextHierarchy({
	@ContextConfiguration(classes = AppConfig.class),
    @ContextConfiguration(classes = WebMvcConfig.class)
})


  • @WebAppConfiguration : Controller 및 web환경에 사용되는 빈을 자동으로 생성하여 등록


MockMVC 실행 : perform()

  • perform() + 요청설정 메소드 : 요청에 대한 설정
  • perform() + Expect 메소드 : 테스트 진행
@Test
public void testController() throws Exception{
	mockMvc.perform(
        get("test"))
    	.param("query", "부대찌개")
        .cooke("쿠키 값")
        .header("헤더 값:)
        .contentType(MediaType.APPLICATION.JSON)
        .content("json으로")
        
        .andExpect(status().isOk()) // 여기부터 검증
        .andExpect(content().string("expect json값"))
        .andExpect(view().string("뷰이름"));
        
        .andDo(print()) //여기부터 기타 메소드
        .andDo(log());

status 검증 -> content 검증 -> view 검증
1개라도 통과하지 않으면 테스트는 fail

MockMVC 요청설정 메소드

  • param, params : 쿼리스트링 설정
  • cookie : 쿠키설정
  • requestAttr : 요청 스코프객체 설정
  • sessionAttr : 세션 스코프객체 설정
  • content : 요청본문 설정
  • header, headers : 요청헤더 설정
  • contentType : 본문타입 설정

검증 메소드

  • status : 상태코드 검증
  • header : 응답 header 검증
  • content : 응답본문 검증
  • cookie : 쿠키상태 검증
  • view : 컨트롤러가 반환한 뷰이름 검증
  • redirectedUrl(Pattern) : 리다이렉트 대상의 경로 검증
  • model : 스프링 MVC 모델 상태 검증
  • request : 세션스코프, 비동기 처리, 요청스코프 상태 검증
  • forwardedUrl : 이동대상의 경로 검증

기타 메소드

  • andDo() : print, log 사용할 수 있는 메소드
    • print() : 실행결과 출력
    • log() : 실행결과를 디버깅 레벨로 출력


MockMVC로 Controller API Test

@Autowired
private MockMvc mockMvc;

@Test
class ControllerTest{
	
    @Autowired
    private MockMvc mockMvc; // mockMvc 생성
    
    @Test
    public void testController() throws Exception{
    	
        String jjson = "{\"name\": \"부대찌개\"}";
        
        //mockMvc에게 컨트롤러에 대한 정보를 입력
        
        mockMvc.perform(
        get("test?query=food") //해당 url로 요청
        .contentType(MediaType.APPLICATION_JSON) // Json 타입으로 지정
        .content(jjson) // jjson으로 내용 등록
        
        .andExpect(status().isOk()) // 응답 status를 ok로 테스트
        .andDo(print()); // 응답값 print
        )
        
        }
}
  1. MockMVC 생성하기
  2. MockMVC에게 요청에 대한 정보 입력하기
  3. 요청에 대한 응답값을 Expect를 이용하여 테스트
    1. Expect가 모두 통과하면 테스트통과
    2. Expect가 1개라도 실패하면 테스트 실패



지난번 예시보다 쉬운 예시
둘 다 해보기!


Reference
https://ronick-grammer.github.io/spring/Spring-Mock-%ED%85%8C%EC%8A%A4%ED%8A%B8/
https://itmore.tistory.com/entry/MockMvc-%EC%83%81%EC%84%B8%EC%84%A4%EB%AA%85
https://goodteacher.tistory.com/257

업데이트: