본문 바로가기

개발 Note/SPRING

[SPRING] Spring Boot 단위 테스트 (1) - Controller

Spring Boot 단위 테스트에 대해 알아보자.

이 기능을 알기 전에는 아마도.. 직접 웹을 띄워 테스트를 하거나

API tester를 이용했던 것 같다. tomcat이 올라갈 때 까지 기다리고,, 에러나면 어디서 났는지 로그 보고,,찾고,,

인류발전 만만세,,😆

 

❓ 단위테스트란?

TDD의 첫 번째 단계인 기능 단위의 테스트 코드를 작성하는 것을 말한다. (필수는 아님 => 그러나 지향해야한다.)

※ TDD?

테스트 주도 개발이다. 테스트 코드를 먼저 작성한 후 개발을 한다. 순서는 레드 그린 사이클을 따른다.

레드 그린 싸이클

1. RED: 항상 실패하는 테스트를 먼저 작성

2. GREEN: 테스트가 통과하는 프로덕션 코드를 작성

3. REFACTOR: 테스트가 통과하면 프로덕션 코드를 리팩토링

 

 

❓ 왜 지향해야 할까?

개발 단계 초기에 문제를 발견할 수 있다. 앞서 얘기한 것 처럼 이미 전체를 구현하고 서버를 실행시켰을 때 기능 중에 하나가 오류가 발생한 경우 찾아내기가 더 까다로울 수 있다.

각 기능에 대한 단위테스트가 있다면 사전에 검증하여 오류를 잡아낼 수 있다.

 

Spring Boot에서는 org.springframework.boot:spring-boot-start-test를 지원한다.

여기서 간단히 테스트에 필요한 라이브러리들을 제공한다.

 

 

✅ 사용해보기

 

1) build.gradle에 test 추가하기

 

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-security'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.apache.pdfbox:pdfbox:2.0.1'
	compileOnly 'org.projectlombok:lombok'
	annotationProcessor 'org.projectlombok:lombok'
	
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testImplementation 'org.springframework.security:spring-security-test'
	testCompileOnly 'org.projectlombok:lombok'
	testAnnotationProcessor 'org.projectlombok:lombok'
}

 

아, 참.

이 프로젝트를 구현할 때 처음 설정했던 프로젝트 이름을 이후 작업 중에 변경하였었다.

그랬더니 빌드가 안되고 오류가 떠서 자바 버전이 문제인지 혹시 옵션 설정이 뭐가 잘못되었는지 한 30분 고민했던 것 같은데 setting.gradle에 rootProject 이름 안바꿈 ^^ 혹시 나중에도 이런 일이 생길까봐 적어놓는다.

 

 

 

2) 테스트를 위한 Controller 만들기

 

@RestController
public class FirstController {
	@PostMapping("/first")
	public String hello(UserInfo user) throws Exception {
		return user.getId() + "의 테스트";
	}
}

 

POST HTTP Method로 요청을 받는 API를 작성하고 이 클래스를 JSON으로 반환하는 컨트롤러로 만들기 위해 @RestController 어노테이션을 추가한다.

 

 

3) DTO 추가

 

public class UserInfo {
    private String id;
    
    public UserInfo() {
    }
    
    public UserInfo(String id) {
    	this.id = id;
    }
 }

 

 

4) 테스트 코드 작성하기

 

@WebMvcTest(controllers = FirstController.class)
class FirstControllerTest {
	
	@Autowired
	private MockMvc mvc;

	@Autowired
	private ObjectMapper objectMapper;
	
	@Test
	public void test() throws Exception {
		
		String content = objectMapper.writeValueAsString(new UserInfo("sylim"));
		mvc.perform(post("/first")
				   .content(content)
				   .contentType(MediaType.APPLICATION_JSON)
				   .accept(MediaType.APPLICATION_JSON))
				   .andExpect(status().isOk())
				   .andDo(print());
		
	}

}

 

 

어노테이션과 기능에 대해 알아보자.

 

버전 Spring MVC 테스트 단위 테스트(Mockito) Spring 통합테스트
2.2 이전 @RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest
2.2 이후 @WebMvcTest @ExtendWith(MockitoExtension.class) @SpringBootTest

- @Autowired : Spring이 관리하는 Bean을 주입받는다.

- MockMvc : 웹 API를 테스트할 때 사용한다. (HTTP GET, POST 등에 대한 API 테스트 가능)

- content : 응답에 대한 정보를 검증해준다.

- perform(post("/first")) : MockMvc를 통해 HTTP 요청을 한다.

- andExpect(status().isOk()) : perform의 결과를 검증한다. 

* 상태코드(status())

  • isOk() : 200
  • isNotFound() : 404
  • isMethodNotAllowed(): 405
  • isInternalServerError(): 500
  • is(int status): status 상태 코드

- andDo(print()) : 요청/응답 전체 메세지를 확인할 수 있다.

 

 

 

5) 실행하기

 

 

JUnit테스트로 실행하면 성공한 화면과 전체 메세지를 확인할 수 있다.

 

 


👁‍🗨 마치며

어떻게 보면 번잡스럽기도, 어떻게 보면 편하기도 한 기능이다.

어떻게 활용하느냐는 개발자의 몫이니 열심히 사용해보도록 하자. 기능 하나 하나 테스트를 해가는 것이 전체 프로젝트의 오류를 줄일 수 있을 것이다. 

'개발 Note > SPRING' 카테고리의 다른 글

[SPRING] Spring AOP  (0) 2022.06.14
[SPRING] Spring boot - 외부 jar 추가 후 테스트하기  (0) 2022.04.23
[SPRING] Spring Security  (0) 2022.03.26