스터디 날짜 및 장소
- 매주 화요일 9시 - 10시 30분
- 208관 6층 팀플실4
지난주 스터디
- 인텔리제이 설치
- 인텔리제이에서 프로젝트 생성
- 깃 연결
- 객체지향 프로그래밍(OOP)
스터디 내용
테스트 코드 작성
- 테스트 코드 없이 개발하는 경우
- 코드 작성
- 프로그램 실행
- API 테스트 도구로 HTTP 요청
- 요청결과를 System.out.println()으로 검증
- 결과가 다르면 프로그램 중지하고 코드 수정
→ 2~5번 과정을 코드 수정할 때마다 반복
- 테스트 코드의 장점
- 개발 초기 단계에 문제 발견 가능
- 나중에 코드 리팩토링 또는 라이브러리 업그레이드 등에서 기존 기능이 올바르게 작동하는지 확인 가능
- 기능에 대한 불확실성 감소
- 시스템에 대한 실제 문서 제공
- xUnit
- JUnit - Java
- DBUnit - DB
- CppUnit - C++
- NUnit - .net
테스트 코드 작성을 도와주는 가장 대중적인 프레임워크
- 간단한 API 생성
DemoApplication.java
package com.example.demo.web; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
- @SpringBootApplication
스프링 부트의 자동설정, 스트링 Bean 읽기와 생성을 자동으로 설정
이 위치부터 설정을 읽기 때문에 이 클래스는 항상 프로젝트의 최상단에 위치
- SpringApplication.run()
내장 AWS 실행하여 같은 환경에서 스프링부트를 배포할 수 있게 한다.
src>main>java>com.example.demo>web>HelloController.java 생성
package com.example.demo.web.web; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @GetMapping("/hello") public String hello(){ return "hello"; } }
- @RestController
컨트롤러를 JSON으로 반환하는 컨트롤러로 만들어준다.
- @GetMapping
Get 요청을 받을 수 있는 API를 만들어준다.
test>DemoApplicationTests.java 생성
package com.example.demo.web; import com.example.demo.web.web.HelloController; import org.junit.jupiter.api.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @RunWith(SpringRunner.class) @WebMvcTest(controllers = HelloController.class) public class DemoApplicationTests { @Autowired private MockMvc mvc; @Test public void return_hello() throws Exception{ String hello = "hello"; mvc.perform(get("/hello")) .andExpect(status().isOk()) .andExpect(content().string(hello)); } }
- @RunWith(SpringRunner.class)
테스트 시 JUnit에 내장된 것 외에 다른 실행자를 실행
스프링부트 테스트와 JUnit 사이의 연결자 역할
- @WebMvcTest
컨트롤러 계층 만을 슬라이스 테스트할 수 있도록 도와주는 어노테이션
- @Autowired
스프링이 관리하는 Bean을 주입받는다.
- private MockMvc mvc
웹 API를 테스트할 때 사용
- mvc.perform(get(”/hello”))
MockMvc를 통해 /hello 주소로 HTTP GET 요청
- .andExpect(status().isOk())
mvc.perform의 결과 검증
HTTP Header의 Status 검증
- .andExpect(content().string(hello))
mvc.perform의 결과 검증
응답 본문의 내용 검증
Controller에서 반환하는 “hello” 값이 맞는지 검증
롬복 설치 및 코드 전환
- 롬복
Java를 개발할 때 자주 사용하는 코드를 어노테이션으로 자동 생성해준다.
ex) getter, setter, 기본생성자, toString 등
- 롬복 설치
File>Settings>Plugins>Lombok 설치
build.gradle의 dependencies에 아래 코드 추가
dependencies{ implementation('org.projectlombok:lombok') annotationProcessor('org.projectlombok:lombok') testImplementation('org.projectlombok:lombok') testAnnotationProcessor('org.projectlombok:lombok') }
- HelloController 코드를 롬복으로 전환
- 문제 발생 여부 확인하는 코드
롬복으로 변경했을 때 문제가 생기는지 테스트 코드를 돌려보면 알 수 있다.
src>main>java>com.example.demo>web>dto 패키지생성>HelloResponseDto.java 생성
package com.example.demo.web.web.dto; import lombok.Getter; import lombok.RequiredArgsConstructor; @Getter @RequiredArgsConstructor public class HelloResponseDto { private final String name; private final int amount; }
선언된 모든 필드의 get메소드를 생성
선언된 모든 final 필드가 포함된 생성자를 생성
final이 없는 필드는 생성자에 포함되지 않는다.
test>java>com.example.demo>dto패키지 생성>HelloResponseDtoTest.java 생성
package com.example.demo.web.dto; import com.example.demo.web.web.dto.HelloResponseDto; import org.junit.jupiter.api.Test; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; public class HelloResponseDtoTest { @Test public void lombokTest(){ String name = "test"; int amount = 1000; HelloResponseDto dto = new HelloResponseDto(name,amount); assertThat(dto.getName()).isEqualTo(name); assertThat(dto.getAmount()).isEqualTo(amount); } }
assertj라는 테스트 검증 라이브러리의 검증 메소드
검증하고 싶은 대상을 메소드 인자로 받는다.
HelloController.java
package com.example.demo.web.web; import com.example.demo.web.web.dto.HelloResponseDto; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @GetMapping("/hello") public String hello(){ return "hello"; } @GetMapping("/hello/dto") public HelloResponseDto helloDto(@RequestParam("name") String name, @RequestParam("amount") int amount) { return new HelloResponseDto(name, amount); } }
HelloControllerTest.java
package com.example.demo.web; import org.junit.jupiter.api.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; import static org.hamcrest.Matchers.is; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @RunWith(SpringRunner.class) @WebMvcTest public class HelloControllerTest { @Autowired private MockMvc mvc; @Test public void return_hello() throws Exception{ String hello = "hello"; mvc.perform(get("/hello")) .andExpect(status().isOk()) .andExpect(content().string(hello)); } @Test public void return_helloDto() throws Exception{ String name = "hello"; int amount = 1000; mvc.perform( get("/hello/dto") .param("name",name) .param("amount",String.valueOf(amount))) .andExpect(status().isOk()) .andExpect(jsonPath("$.name",is(name))) .andExpect(jsonPath("$.amount",is(amount))); } }
API 테스트 시 사용될 요청 파라미터 설정
값은 String만 허용
JSON 응답값을 필드별로 검증할 수 있는 메소드
“$”를 기준으로 필드명 명시
해당 코드를 실행하면 JSON이 리턴되는 API도 정상적으로 테스트 통과하는 것을 확인할 수 있다.