inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

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

BDDMockito

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

904

Louie(루이)

작성한 질문수 16

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()
    }
}

 

spring tdd jpa mockito 소프트웨어-테스트 junit5

답변 2

0

박우빈

안녕하세요, min102 님!

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

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

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

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

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

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

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

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

0

인프런 AI 인턴

안녕하세요, 인프런 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())를 추가하여 요청과 응답에 대한 자세한 내용을 출력하고 있으시다면, 이 출력된 로그를 통해 좀 더 구체적인 원인을 파악하는 데 도움이 될 것입니다.

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

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

private 상수 테스트 관련 질문

0

82

1

void는 어떻게 테스트하나요..? void로 애초에 코딩하면 안되나요??

0

124

2

커버리지는 어떻게 활용하시는지 궁금합니다.

0

159

2

테스트 문서화 질문입니다

0

104

2

단위테스트 질문이 있습니다

0

95

2

컨트롤러는 모킹을 한 이유가 궁금합니다.

0

100

2

ERD 가장자리에 있는 도메인 테스트 질문

0

87

2

DTO 검증 필드에 대한 테스트 코드 작성은 어디까지?

0

132

2

OrderCreateRequest DTO에 대해서 궁금한점

0

101

2

고전파의 테스트 대역 사용 대상, 공유 의존성

0

154

2

계층 관련 질문이 있습니다.

0

137

3

'코틀린'에서는 빌더를 따로 쓰지 않는데, 이 때는 어떻게 test fixture를 만드시는지 궁금합니다

1

122

2

혹시 update 로직은 어떻게 테스트하나요? (@Setter?)

0

133

2

단위테스트와 통합테스트의 경계가 궁금합니다.

0

227

2

Service+Repository 통합테스트 관련 질문입니다.

0

149

2

OrderControllerDocsTest 작성 해봤는데요. 날짜 형식이 이상하게 나와요

0

183

2

test 용 .yml

0

89

2

throws Exception

0

78

2

카페키오스크 클래스 문의 ,,

0

87

2

Rest docs 문서용 테스트코드를 따로 작성해야 되나요?

0

172

2

테스트 코드에서 필요한 생성자

0

137

1

tearDown 순서

0

115

2

@Builder 생성자 private

0

135

2

@DisplayName gradle / intellJ

0

92

2