인프런 커뮤니티 질문&답변

min102님의 프로필 이미지
min102

작성한 질문수

Practical Testing: 실용적인 테스트 가이드

BDDMockito

이상한 url로 요청해도 200이 반환됩니다. 그리고 body가 비어있어요...

작성

·

758

0

@WebMvcTest(CompanyController::class)
@ActiveProfiles("test")
@WithMockUser
class CompanyControllerTest {

    @Autowired
    lateinit var mockMvc: MockMvc

    @MockBean
    lateinit var getCompanyService: GetCompanyService

    @MockBean
    lateinit var adminAuthorizationFilter: AdminAuthorizationFilter

    private val cookie = Cookie(ADMIN_AUTH_TOKEN, "admin-auth-token")

    @DisplayName("회사 목록 조회")
    @Test
    fun findAll() {
        // given
        val companies = listOf(
            companyEntity(1, "A"),
            companyEntity(2, "B"),
            companyEntity(3, "C"),
        )
        `when`(getCompanyService.findAll()).thenReturn(companies)

        // when
        val request = MockMvcRequestBuilders.get("/admin/api/v1/companies")
            .cookie(cookie).accept(MediaType.APPLICATION_JSON)

        // then
        mockMvc.perform(request)
            .andExpect(MockMvcResultMatchers.status().isOk)
            .andDo(MockMvcResultHandlers.print())
    }
}

 

위 코드를 가지고 질문드리겠습니다.

 

  1. val request = MockMvcRequestBuilders.get("/admin/api/v1/companies") 이 부분에서 companies가 아니라 존재하지 않는 url(ex. /admin/api/v1/cfasfsdfcompanies

    )라고 한 후 위 코드를 돌리면 200나옵니다. 존재하지 않는 url도 호출이 가능한건가요?

  2. 그리고 body가 항상 빈 값입니다.

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = [Vary:"Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers", X-Content-Type-Options:"nosniff", X-XSS-Protection:"0", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
     Content type = null
             Body = 
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

목킹이 잘못되었는지 점검해보려고 getCompanyService.findAll() 를 호출해보았는데 3개가 정상적으로 나옵니다.

 

혹시 몰라 소스 공유드립니다.

// controller
@RestController
@RequestMapping("/admin/api/v1/companies")
class CompanyController(
    private val getCompanyService: GetCompanyService
) {
    @GetMapping
    fun findAll(): List<CompanyResponse> {
        return getCompanyService.findAll().map { CompanyResponse.of(it) }
    }
}

// service
@Service
@Transactional(readOnly = true)
class GetCompanyService(
    private val companyFindService: CompanyFindService
) {
    fun findAll(): List<CompanyEntity> {
        return companyFindService.findAll()
    }
}

 

답변 2

0

박우빈님의 프로필 이미지
박우빈
지식공유자

안녕하세요, min102 님!

제가 보기에 올려주신 코드 기반으로는 문제가 될 만한 부분이 보이질 않습니다.
존재하지 않는 URL을 호출하면 404가 와야하고, mocking이 정상적으로 잘 되었다면 body도 잘 만들어졌어야 하는데요.

일단 제가 체크해보시라 말씀드릴 수 있는 것은,

  • Controller 코드에 디버거 포인트를 걸어서 step by step으로 MockBean 주입이 잘 되었는지, mocking이 잘 되었는지 확인하기

  • 테스트 코드의 패키지 위치가 올바른지, 테스트에 영향을 미치지는 않는지 (bean 스캔 등)

  • @WebMvcTest 와 관련한 다른 설정이 없는지

  • @ActiveProfile("test") 와 관련해서 해당 프로파일이 동작할 때 기타 다른 설정이 없는지

지금으로서는 해당 코드 자체의 문제라기보다는, 그 외적인 포인트에 대해 하나하나 의심해보는 수밖에 없을 것 같습니다.

한번 다시 차근차근 시도해보시고, 말씀 주세요. 감사합니다 🙂

0

안녕하세요, 인프런 AI 인턴입니다.

min102님의 질문에 답변 드립니다.

  1. @WebMvcTest를 사용할 때에는 실제로 애플리케이션에 있는 모든 URL 매핑이 활성화되는 것이 아닙니다. 이 애노테이션은 주로 MVC 레이어의 슬라이스 테스트(slice test)를 위해 사용되며, 특정 컨트롤러의 빈만 스캔합니다. 따라서 다른 컨트롤러의 매핑 URL은 호출 대상에서 제외됩니다. 그렇기 때문에 존재하지 않는 URL로 요청을 해도, 에러 대신에 스프링 MVC 테스트 구조의 기본 동작으로 인해 OK 상태(200)를 반환하는 경우가 있을 수 있습니다. 호출 대상이 되는 컨트롤러가 올바르게 지정되었는지 확인해 보세요.

  2. body가 비어 있는 경우:

먼저 @WebMvcTest(CompanyController::class) 애노테이션이 CompanyController에 대해서만 컨트롤러 레이어를 테스트하기 위한 설정이 포함되어 있는지 확인하십시오. 그리고 mockMvc.perform(request) 호출 이후에 예상되는 body 내용을 검증하는 .andExpect(MockMvcResultMatchers.content().string(예상되는_내용)) 구문이 포함되어 있는지 검토해보세요. 테스트 코드에서 getCompanyService.findAll()이 실제로 호출되고 정상적인 값을 반환한다면, 응답 본문에 해당 결과가 잘 반영되어야 합니다. andExpect(..)를 통해 실제로 원하는 응답이 오는지 또한 체크가 필요합니다.

예상되는 응답 내용을 검증하는 단계를 추가하지 않았거나, mockMvc 설정에 문제가 있을 수 있습니다. 응답 본문(Body)이 비어 있는 경우 이러한 상황을 의심할 수 있습니다.

예시 코드에 .andDo(MockMvcResultHandlers.print())를 추가하여 요청과 응답에 대한 자세한 내용을 출력하고 있으시다면, 이 출력된 로그를 통해 좀 더 구체적인 원인을 파악하는 데 도움이 될 것입니다.

또한, 컨트롤러에서 예외 발생 시 이를 적절히 처리하고 있는지, 그리고 이에 대한 테스트가 구현되어 있는지도 같이 확인해보세요.

이상으로 질문에 대한 답변을 마치겠습니다. 추가적인 궁금증이 있으시면 질문해 주세요.

min102님의 프로필 이미지
min102

작성한 질문수

질문하기