*모든 내용은 책에 있는 내용을 기반으로 작성하였습니다.
2장 ----
TDD와 UnitTest(단위 테스트)
테스트가 주도하는 개발, 테스트 코드를 먼저 작성한다.
레드 그린 사이클이라는 것이있다.
항상 실패라는 테스트를 먼저 작성하고(Red) ->
테스트가 통과하는 프로덕션 코드를 작성하고(Green) ->
테스트가 통과하면 프로덕션 코드를 리팩토링한다.(Refactor)
단위 테스트는 TDD의 첫번째 단계인 기능 단위위 테스트 코드를 작성하는 것을 이야기한다.
순수하게 테스트 코드만 작성하는것을 이야기한다.
단위 테스트는 개발단계 초기에 문제를 발견하게 도와준다.
단위 테스트는 개발자가 나중에 코드를 리팩토링 하거나 라이브러리 업그레이드 등에서
기존 기능이 올바르게 작동하는지 확인할 수 있다. (ex. 회귀테스트)
단위 테스트는 기능에 대한 불확실성을 감소 시킬 수 있다.
단위 테스트는 기능에 대한 불확실성을 감소시킬 수 있습니다.
단위 테스트는 시스템에 대한 실제 문서를 제공한다. 단위 테스트 자체가 문서로 사용될 수 있다.
일반적으로 패키지명은 웹 사이트 주소의 역순이다.
웹사이트 주소가 admin.jojoldu.com 이라면
패키지명은 com.jojoldu.admin 이다.
package com.jojoldu.book.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
메인 클래스 역할을 한다.
@SpringBootApplication 으로 인해 스프링 부트의 자동 설정, 스프링 Bean 읽기와 생성을 모두 자동으로 설정한다. 특히 @SpringBootApplication 이 있는 위치부터 설정을 읽어가기 때문에 프로젝트 최상단에 위치해야한다.
main 메소드 안에 SpringApplication.run으로 인해 내장 WAS를 실행한다.
내장WAS : Web Application Server - 별도로 외부에 WAS를 두지 않고 애플리케이션을 실행할 때 내부에서 WAS를 실행하는 것
이렇게 되면 항상 서버에 Tomcat을 설치할 필요가 없어지며, 스프링 부트에서 만들어진 Jar파일로 실행하면 된다. (Jar : 실행가능한 java 패키징 파일)
언제 어디서나 같은 환경에서 스프링 부트를 배포할 수 있기에 사용 권장
외장 WAS 를 사용하게 된다면 모든 서버는 WAS의 종류와 버전, 설정을 일치시켜야만 하므로 모든 서버가 같은 환경을 구축해야만 해서 힘들어진다.
package com.jojoldu.book.springboot.web;
import com.jojoldu.book.springboot.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 // (1)
public class HelloController {
@GetMapping("/hello") // (2)
public String hello(){
return "hello";
}
}
Test 코드를 만들때는 src/test/java에 같은 패키지 이름으로 다시 만들어주며
class이름은 대상 클래스 이름에 Test를 붙인다.
package com.jojoldu.book.springboot.web;
import org.junit.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.*;
import static org.hamcrest.Matchers.is;
@RunWith(SpringRunner.class) // (1)
@WebMvcTest(controllers = HelloController.class) // (2)
public class HelloControllerTest {
@Autowired // (3)
private MockMvc mvc; // (4)
@Test
public void hello가_리턴된다() throws Exception{
String hello = "hello";
mvc.perform(get("/hello")) // (5)
.andExpect(status().isOk()) // (6)
.andExpect(content().string(hello)); // (7)
}
}
책의 내용 따름
package com.jojoldu.book.springboot.web.dto;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class HelloResponseDtoTest {
@Test
public void 롬복_기능_테스트(){
//given
String name ="test";
int amount =1000;
//when
HelloResponseDto dto = new HelloResponseDto(name,amount);
//then
assertThat(dto.getName()).isEqualTo(name); // (1), (2)
assertThat(dto.getAmount()).isEqualTo(amount);
}
}
*assertj의 장점 : 추가적으로 라이브러리가 필요하지 않고, 자동완성이 더 확실하게 지원된다.
package com.jojoldu.book.springboot.web;
import com.jojoldu.book.springboot.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, // (3)
@RequestParam("amount") int amount){
return new HelloResponseDto(name,amount);
}
}
package com.jojoldu.book.springboot.web;
import org.junit.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.*;
import static org.hamcrest.Matchers.is;
@RunWith(SpringRunner.class)
@WebMvcTest(controllers = HelloController.class)
public class HelloControllerTest {
@Autowired
private MockMvc mvc;
@Test
public void hello가_리턴된다() throws Exception{
String hello = "hello";
mvc.perform(get("/hello"))
.andExpect(status().isOk())
.andExpect(content().string(hello));
}
@Test
public void helloDto가_리턴된다() throws Exception{
String name ="hello";
int amount = 1000;
mvc.perform(get("/hello/dto").
param("name",name). // (1)
param("amount",String.valueOf(amount)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name", is(name))) // (2)
.andExpect(jsonPath("$.amount",is(amount)));
}
}