본문 바로가기
개발/Spring

Controller Test

by BellOne4222 2024. 2. 18.

@SpringBootTest

  • 통합테스트 하기에 적절
  • 애플리케이션 컨텍스트를 로드하는데 시간이 걸려서 테스트가 다소 무거운 편이다.
  • @SpringBootTest
    • @BootstrapWith + @ExtendWith
    • JUnit5를 사용 할때 @ExtendWith(SpringExtension.class) 쓰면 안된다.
  • @Test
    • JUnit5 애노테이션
    • 단위 테스트 메소드 지정

@SpringBootTest properties 

• value, properties: 프로퍼티 설정
 • args: 애플리케이션 실행 시 커맨드라인으로 입력하는 인자(옵션) 설정
 • classes: ApplicationContext 로딩을 위한 설정 클래스를 직접 지정
 • webEnvironment: ApplicationContext 의 웹 환경 설정
 • WebEnvironment.MOCK: mock servlet, embedded server 동작 x
 • @AutoConfigureMockMvc, @AutoConfigureWebTestClient 와 함께 써서 mock test 가능
 • WebEnvironment.RANDOM_PORT: 랜덤 포트, embedded server 동작
 • WebEnvironment.DEFINED_PORT: 포트 지정(server.port), embedded server 동작
 • WebEnvironment.NONE: 웹 환경 구성 안 함, embedded server 동작 x

 

Auto-configured Test(Slice Test)

  • 스프링 애플리케이션에서 내가 필요한 일부분의 자동 설정만 불러오는 방법

•  @DataCassandraTest
•  @DataJdbcTest
•  @DataJpaTest
•  @DataLdapTest
•  @DataMongoTest
•  @DataNeo4jTest
•  @DataR2dbcTest
•  @DataRedisTest
•  @JdbcTest
•  @JooqTest
•  @JsonTest
•  @RestClientTest
•  @WebFluxTest
•  @WebMvcTest
• @WebServiceClientTest

 

@WebMvcTest

  • spring mvc 컨트롤러 레이어를 슬라이스 테스트 할 때 사용
  • mockmvc 빈을 자동 설정하고 테스트에 사용
  • 로드할 컨트롤러 클래스를 지정 가능(기본 동작 : 전체 컨트롤러 로드)

 

@AutoConfigureMockMvc // MockMvc를 자동으로 구성하여 테스트에 사용
@SpringBootTest // 스프링 부트 애플리케이션을 로드하여 테스트를 실행
class BaseControllerTest {

	@Autowired
	private MockMvc mvc; // MockMvc를 주입하여 사용

	@DisplayName("[view][GET] 기본 페이지 요청")
	@Test // 테스트 메서드 선언
	void testRoot() throws Exception {
		// Given (주어진 상황)

		// When (언제)

		// Then (그러면)
		mvc.perform(get("/")) // "/" 경로에 GET 요청 수행
			.andExpect(status().isOk()) // HTTP 상태가 OK인지 확인
			.andExpect(content().contentTypeCompatibleWith(MediaType.TEXT_HTML)) // 응답의 콘텐츠 타입이 text/html과 호환되는지 확인
			.andExpect(content().string(containsString("default"))) // 응답 콘텐츠에 "default" 문자열이 포함되어 있는지 확인
			.andExpect(view().name("index")) // 뷰의 이름이 "index"인지 확인
			.andDo(print()); // 수행한 결과를 출력
	}
}

 

테스트 결과

 

Slice Test로 변환(@WebMvcTest)

@WebMvcTest(BaseController.class) // BaseController를 테스트하기 위한 설정
class BaseControllerTest {

	private final MockMvc mvc; // MockMvc 객체 선언

	// 생성자 주입
	public BaseControllerTest(@Autowired MockMvc mvc) {
		this.mvc = mvc; // MockMvc 객체 주입
	}

 

// APIPlaceController Test

@WebMvcTest(ApiPlaceController.class) // ApiPlaceController를 테스트하기 위한 웹 MVC 테스트
class ApiPlaceControllerTest {

	private final MockMvc mvc; // MockMvc 객체 선언

	public ApiPlaceControllerTest(@Autowired MockMvc mvc) { // 생성자를 통한 주입
		this.mvc = mvc;
	}

	@DisplayName("[API][GET] 장소 리스트 조회 - 장소 리스트 데이터를 담은 표준 API 출력")
	@Test // 테스트 메서드 선언
	void givenNothing_whenRequestingPlaces_thenReturnsPlacesInStandardResponse() throws Exception {
		// Given (주어진 상황)

		// When & Then (언제 & 그러면)
		mvc.perform(get("/api/places")) // "/api/places" 경로에 GET 요청 수행
			.andExpect(status().isOk()) // HTTP 상태가 OK인지 확인
			.andExpect(content().contentType(MediaType.APPLICATION_JSON)) // 응답의 콘텐츠 타입이 JSON인지 확인
			.andExpect(jsonPath("$.data").isArray()) // 응답 데이터의 "data" 필드가 배열인지 확인
			.andExpect(jsonPath("$.data[0].placeType").value(PlaceType.COMMON.name())) // 첫 번째 데이터의 장소 타입이 COMMON인지 확인
			.andExpect(jsonPath("$.data[0].placeName").value("랄라배드민턴장")) // 첫 번째 데이터의 장소 이름이 "랄라배드민턴장"인지 확인
			.andExpect(jsonPath("$.data[0].address").value("서울시 강남구 강남대로 1234")) // 첫 번째 데이터의 주소가 "서울시 강남구 강남대로 1234"인지 확인
			.andExpect(jsonPath("$.data[0].phoneNumber").value("010-1234-5678")) // 첫 번째 데이터의 전화번호가 "010-1234-5678"인지 확인
			.andExpect(jsonPath("$.data[0].capacity").value(30)) // 첫 번째 데이터의 수용 가능 인원이 30인지 확인
			.andExpect(jsonPath("$.data[0].memo").value("신장개업")) // 첫 번째 데이터의 메모가 "신장개업"인지 확인
			.andExpect(jsonPath("$.success").value(true)) // 응답의 success 필드가 true인지 확인
			.andExpect(jsonPath("$.errorCode").value(ErrorCode.OK.getCode())) // 응답의 errorCode 필드가 OK 코드인지 확인
			.andExpect(jsonPath("$.message").value(ErrorCode.OK.getMessage())); // 응답의 message 필드가 OK 메시지인지 확인
	}

	@DisplayName("[API][GET] 단일 장소 조회 - 장소 있는 경우, 장소 데이터를 담은 표준 API 출력")
	@Test // 테스트 메서드 선언
	void givenPlaceId_whenRequestingExistentPlace_thenReturnsPlaceInStandardResponse() throws Exception {
		// Given (주어진 상황)
		int placeId = 1; // 장소 ID

		// When & Then (언제 & 그러면)
		mvc.perform(get("/api/places/" + placeId)) // "/api/places/{placeId}" 경로에 GET 요청 수행
			.andExpect(status().isOk()) // HTTP 상태가 OK인지 확인
			.andExpect(content().contentType(MediaType.APPLICATION_JSON)) // 응답의 콘텐츠 타입이 JSON인지 확인
			.andExpect(jsonPath("$.data").isMap()) // 응답 데이터의 "data" 필드가 Map인지 확인
			.andExpect(jsonPath("$.data.placeType").value(PlaceType.COMMON.name())) // 장소 타입이 COMMON인지 확인
			.andExpect(jsonPath("$.data.placeName").value("랄라배드민턴장")) // 장소 이름이 "랄라배드민턴장"인지 확인
			.andExpect(jsonPath("$.data.address").value("서울시 강남구 강남대로 1234")) // 주소가 "서울시 강남구 강남대로 1234"인지 확인
			.andExpect(jsonPath("$.data.phoneNumber").value("010-1234-5678")) // 전화번호가 "010-1234-5678"인지 확인
			.andExpect(jsonPath("$.data.capacity").value(30)) // 수용 가능 인원이 30인지 확인
			.andExpect(jsonPath("$.data.memo").value("신장개업")) // 메모가 "신장개업"인지 확인
			.andExpect(jsonPath("$.success").value(true)) // 응답의 success 필드가 true인지 확인
			.andExpect(jsonPath("$.errorCode").value(ErrorCode.OK.getCode())) // 응답의 errorCode 필드가 OK 코드인지 확인
			.andExpect(jsonPath("$.message").value(ErrorCode.OK.getMessage())); // 응답의 message 필드가 OK 메시지인지 확인
	}

	@DisplayName("[API][GET] 단일 장소 조회 - 장소 없는 경우, 빈 표준 API 출력")
	@Test // 테스트 메서드 선언
	void givenPlaceId_whenRequestingNonexistentPlace_thenReturnsEmptyStandardResponse() throws Exception {
		// Given (주어진 상황)
		int placeId = 2; // 존재하지 않는 장소의 ID

		// When & Then (언제 & 그러면)
		mvc.perform(get("/api/places/" + placeId)) // "/api/places/{placeId}" 경로에 GET 요청 수행
			.andExpect(status().isOk()) // HTTP 상태가 OK인지 확인
			.andExpect(content().contentType(MediaType.APPLICATION_JSON)) // 응답의 콘텐츠 타입이 JSON인지 확인
			.andExpect(jsonPath("$.data").isEmpty()) // 응답 데이터의 "data" 필드가 비어 있는지 확인
			.andExpect(jsonPath("$.success").value(true)) // 응답의 success 필드가 true인지 확인
			.andExpect(jsonPath("$.errorCode").value(ErrorCode.OK.getCode())) // 응답의 errorCode 필드가 OK 코드인지 확인
			.andExpect(jsonPath("$.message").value(ErrorCode.OK.getMessage())); // 응답의 message 필드가 OK 메시지인지 확인
	}

}

 

결과

'개발 > Spring' 카테고리의 다른 글

MVC 패턴(3) - 비즈니스 로직 구현  (0) 2024.02.19
Test Driven Development(TDD)  (1) 2024.02.18
ControllerAdvice  (0) 2024.02.17
MVC 패턴 - API 설계(2)  (0) 2024.02.17
함수형 프로그래밍  (0) 2024.02.16