↓↓↓ 이전내용
[REST API] Spring Boot로 REST API CRUD 간단 구현 (7) - JUnit TEST service 계층 test 예제
↓↓↓ 이전 내용 2023.12.30 - [Web Application/Backend] - [REST API] Spring Boot로 REST API CRUD 간단 구현 (6) - JUnit TEST 기본 설정 및 repository 계층 test 예제 [REST API] Spring Boot로 REST API CRUD 간단 구현 (6) - JUnit TEST
im-gonna.tistory.com
이전 내용에 이어서 이번에는 최상단 layer인 Controller의 test를 진행해보자.
main에 있는 controller class 이름에 ctrl+shift+t를 눌러서 test 클래스를 자동 생성해준다.
💡 Controller test class
import 되어있는 jupiter assertion은 제거한다. (이전에 설명했지만 기본 assertion 사용!)
- 클래스 어노테이션 추가
외부 data와 직접 상호작용하는 계층이기 때문에 test class에 어노테이션을 추가해준다.

그리고 컨트롤러 클래스를 인자로 가져온다.
- mockMvc 주입

web layer url test이기 때문에, 모의 MVC가 필요하다.
따라서 MockMvc 객체를 하나 선언하여 사용한다.
- 필요한 객체 선언

controller 레이어는 service 레이어와 통신하기 때문에 모의 service를 만들어주어야 한다.
그리고 cloudvendor 인스턴스 2개를 각각 만들어 주고, 이들을 담을 리스트로 하나 선언해준다.
- setUp 메서드

cloudVendorOne 인스턴스와 cloudVendorTwo 인스턴스를 생성해주고, list에 담아준다.
- getCloudVendorDetails()의 test 메서드

- controller에 정의된 getCloudVendorDetails()의 로직을 보면, cloudVendorService의 getCloudVendor()를 호출한 결과를 반환한다.
- 따라서 cloudVendorService의 getCloudVendor()에 cloudVendorId가 1로 전달하며, 이 메서드를 호출하면 cloudVendorOne을 return하여 성공적으로 보이도록 한다.
- 그리고 mockMvc의 perform메서드를 통해 get 동작을 수행하도록 하고 url은 controller에서 지정한대로 cloudVendorId에 따라 달라지므로, /cloudvendor/1 로 가져오도록 한다.
- andDo(print()): 이 메서드는 테스트 결과를 출력한다. 테스트가 실행될 때 컨트롤러가 반환하는 HTTP 응답 등의 정보를 콘솔에 출력하여 디버깅이나 테스트 결과 확인을 도와준다.
- andExpect(status().isOk()): 이 메서드는 특정한 조건을 검증하는데, 여기서는 HTTP 응답의 상태 코드가 "200 OK"인지 확인한다. 만약 상태 코드가 200이 아니면 테스트는 실패하는 것이다.
- 여기까지하면, perform get에서 빨간 줄이 쳐질 것이다. 예외처리가 필요하다. 메서드에 throws Exception을 추가해주자.

테스트 결과 성공이다.
getCloudVendorDetails()의 test를 위해 모의(mock) http 서블릿 요청이 제대로 구축되는 것을 확인할 수 있다.
(이는 마치 레포지토리 레이어에서 내장된 데이터베이스 h2를 사용하는 것과 유사한 상황이다)
파라미터와 헤더는 아무것도 필요로 하지 않았다.
MockHttpServletResponse:
Status = 200
Error message = null
Headers = [Content-Type:"application/json"]
Content type = application/json
Body = {"data":{"vendorId":"1","vendorName":"Amazon","vendorAddress":"USA","vendorPhoneNumber":"xxxxx"},"httpStatus":"OK","message":"Requested Vendor Details are given here"}
Forwarded URL = null
Redirected URL = null
Cookies = []
그 아래 더 내려서 response 부분을 보면, status는 200, 에러 사항 없음, body data에 controller에서 반환하는 CloudVendorOne에 대한 data가 담겨져 있는 것을 확인할 수 있다.
- getAllCloudVendorDetails()의 test 메서드

- 앞의 get메서드와 로직은 유사하나, service 메서드를 getAll로 수정해주고, 가져오는 단위가 list이기 때문에, 초기에 설정해주었던 cloudVendorList를 return하도록 한다.
- 모든 cloudVendor를 가져올 때에는 기본 url을 사용하기 때문에, /cloudvendor로 mapping되도록 한다.

MockHttpServletResponse:
Status = 200
Error message = null
Headers = [Content-Type:"application/json"]
Content type = application/json
Body = [{"vendorId":"1","vendorName":"Amazon","vendorAddress":"USA","vendorPhoneNumber":"xxxxx"},{"vendorId":"2","vendorName":"GCP","vendorAddress":"UK","vendorPhoneNumber":"yyyyy"}]
Forwarded URL = null
Redirected URL = null
Cookies = []
body를 보면 one, tow 모두 값을 가져오는 것을 확인할 수 있다.
- deleteCloudVendorDetails()의 test 메서드

- controller의 delete 메서드 로직을 보면, service의 delete메서드를 호출하고, 이 안에서는 Success 메시지를 반환하도록 되어있다.
- 따라서 cloudvendorId가 1인 cloudvendor를 delete하도록 service 메서드가 호출되면, Success를 return하도록 하여, service의 delete 메서드 호출을 성공적으로 보이게 한다.
- 그리고 mockMvc의 perform을 통해 delete mapping시 url은 /cloudvendor/1에 매핑되도록 한다.

MockHttpServletResponse:
Status = 200
Error message = null
Headers = [Content-Type:"text/plain;charset=UTF-8", Content-Length:"33"]
Content type = text/plain;charset=UTF-8
Body = Cloud Vendor Deleted Successfully
Forwarded URL = null
Redirected URL = null
Cookies = []
response의 body를 보면 controller의 해당 메서드에서 반환하는 값인 메시지를 반환하는 것을 확인할 수 있다.
- createCloudVendorDetails()의 test 메서드

- controller에서 create메서드 로직을 살펴보면, cloudVendorService의 create메서드를 호출한다. 그 메서드 안에서는 success를 return한다.
- 따라서 create메서드가 호출되면 Sucess를 return하도록 한다.
- perform의 post mapping 시 /cloudvendor url과 mapping되도록 한다.
- 그런데, 내용으로 전달되는 data를 json형식으로 전달하여야 하기 때문에, contentType을 json으로 지정해준다.
- 그런데, cloudvendor는 entity이기 때문에, json형식으로 바꾸어주기 위해 위 코드를 작성해준다.
- json 형식의 cloudvendor를 requestJson에 저장해주고, requestJson을 content에 넣는다.

MockHttpServletResponse:
Status = 200
Error message = null
Headers = [Content-Type:"text/plain;charset=UTF-8", Content-Length:"33"]
Content type = text/plain;charset=UTF-8
Body = Cloud Vendor Created Successfully
Forwarded URL = null
Redirected URL = null
Cookies = []
response의 body를 보면 controller의 해당 메서드에서 반환하는 값인 메시지를 반환하는 것을 확인할 수 있다.
- updateCloudVendorDetails()의 test 메서드

- 앞의 create 메서드와 로직이 유사하기 때문에, service 메서드의 create를 update로 변경하고, perform메서드는 post를 put으로 변경한다.

MockHttpServletResponse:
Status = 200
Error message = null
Headers = [Content-Type:"text/plain;charset=UTF-8", Content-Length:"33"]
Content type = text/plain;charset=UTF-8
Body = Cloud Vendor Updated Successfully
Forwarded URL = null
Redirected URL = null
Cookies = []
역시 response의 body에는 controller의 해당 메서드에서 반환하는 값인 메시지를 담고 있다.
모든 unit test를 마쳤으므로, 전체 test class의 test coverage를 확인해보자.

test coverage가 100% 인것을 확인하였다.
summery

↓↓↓ 다음 내용
[REST API] Spring Boot로 REST API 프로젝트 (9) - Swagger로 api document 생성하기
↓↓↓이전내용 2024.01.10 - [Web Application/Backend] - [REST API] Spring Boot로 REST API 프로젝트 (8) - JUnit TEST controller 계층 test 예제 [REST API] Spring Boot로 REST API 프로젝트 (8) - JUnit TEST controller 계층 test 예제 ↓
im-gonna.tistory.com