Test-Driven Development (TDD)는 소프트웨어 개발 프로세스에서 테스트를 먼저 작성하고, 그 테스트를 통과하도록 코드를 구현하는 방법론입니다. Spring Boot를 사용하면 TDD를 효과적으로 실천할 수 있습니다. 이번 블로그 글에서는 Spring Boot에서 TDD를 적용하는 방법과 예제 코드를 알아보겠습니다.
TDD의 기본 원칙
테스트 작성: 기능 구현 전에 실패하는 테스트 코드를 작성합니다.
코드 작성: 작성한 테스트를 통과하도록 최소한의 코드를 작성합니다.
리팩토링: 테스트가 통과한 후, 코드를 개선합니다.
Spring Boot TDD 환경 설정
먼저 Spring Boot 프로젝트를 설정합니다. Spring Initializr(https://start.spring.io/)를 사용하여 기본 프로젝트를 생성할 수 있습니다. 필요한 의존성으로는 Spring Web, Spring Data JPA, H2 Database, Spring Boot DevTools, Spring Boot Starter
이번 예제에서는 사용자(User) 정보를 관리하는 간단한 애플리케이션을 만들어보겠습니다.
1단계: 테스트 작성
먼저, 사용자 저장 기능에 대한 테스트를 작성합니다. src/test/java/com/example/demo/UserControllerTest.java 파일을 생성합니다.
package com.example.demo;
import com.example.demo.controller.UserController;
import com.example.demo.model.User;
import com.example.demo.service.UserService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@AutoConfigureMockMvc
public class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private UserService userService;
@BeforeEach
public void setUp() {
// Mocking UserService
when(userService.save(any(User.class))).thenReturn(new User(1L, "testuser", "test@example.com"));
}
@Test
public void testCreateUser() throws Exception {
String userJson = "{\"name\":\"testuser\",\"email\":\"test@example.com\"}";
mockMvc.perform(post("/users")
.contentType(MediaType.APPLICATION_JSON)
.content(userJson))
.andExpect(status().isCreated());
}
}
2단계: 코드 작성
위의 테스트가 실패하는 것을 확인한 후, 실제 UserController와 UserService를 구현합니다.
User VO
package com.example.demo.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
// Constructors, getters, and setters
}
UserService
package com.example.demo.service;
import com.example.demo.model.User;
import com.example.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public User save(User user) {
return userRepository.save(user);
}
}
UserController
package com.example.demo.service;
import com.example.demo.model.User;
import com.example.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public User save(User user) {
return userRepository.save(user);
}
}
3단계: 리팩토링
테스트가 통과하면, 코드를 리팩토링하여 가독성을 높이고 중복을 제거합니다. 예를 들어, 모든 메서드에 대해 예외 처리를 추가하거나, 서비스 계층을 더 깔끔하게 정리할 수 있습니다.
결론
TDD는 코드 품질을 높이고, 버그를 줄이며, 개발 속도를 향상시키는 데 큰 도움이 됩니다. Spring Boot와 함께 TDD를 활용하면, 테스트를 통해 보다 안정적인 애플리케이션을 개발할 수 있습니다. 위의 예제를 바탕으로 실제 프로젝트에 TDD를 적용해 보시기 바랍니다.