본문 바로가기

개발중/Spring

[스프링] TDD(Test-Driven Development) 필요한 이유와 방법론에 대해

728x90
반응형

TDD(Test-Driven Development)란, 테스트 주도 개발 방법론으로서, 소프트웨어 개발 과정에서 테스트 케이스를 먼저 작성한 후, 해당 테스트를 통과하는 코드를 작성하는 개발 방식입니다. 

이를 통해 높은 품질의 코드를 작성하고, 잠재적인 버그를 줄이며, 리팩토링과 유지보수를 용이하게 할 수 있습니다.

TDD가 필요한 이유

코드 품질 향상

TDD를 통해 높은 품질의 코드를 작성할 수 있습니다.

테스트 케이스를 먼저 작성하면 개발자는 코드를 작성하기 전에 요구사항과 기능에 대해 명확하게 이해할 수 있습니다.

 

버그 감소

TDD는 개발 초기 단계부터 버그를 발견하고 수정할 수 있게 도와줍니다.

이는 장기적으로 시간과 비용을 절약할 수 있습니다.

 

유지보수 용이

테스트 케이스가 작성되어 있으면, 코드 수정 시 테스트를 통해 안전하게 리팩토링을 진행할 수 있습니다.

이는 유지보수 작업을 용이하게 하며 코드의 안정성을 보장합니다.

 

코드 작성 시간 단축

테스트를 통과하는 코드를 작성하게 되면, 빠르게 기능을 구현할 수 있습니다.

또한 코드 리뷰 시간도 줄일 수 있습니다.

 

TDD 방법론

요구사항 분석

먼저 요구사항을 분석하여 명확하게 이해하고, 개발할 기능을 결정합니다.

 

테스트 케이스 작성

해당 기능에 대한 테스트 케이스를 작성합니다. 테스트 케이스는 실패할 것으로 예상되어야 합니다.


코드 작성

테스트 케이스를 통과할 수 있는 코드를 작성합니다.


테스트 실행

작성한 코드를 실행하여 테스트를 수행합니다. 테스트를 통과하지 못하면 코드를 수정하고 다시 테스트를 실행합니다.


리팩토링

코드를 최적화하고 중복을 제거하여 가독성과 성능을 향상시킵니다. 리팩토링 후에도 테스트를 통과해야 합니다.
이러한 과정을 반복하여 개발을 진행합니다. 

스프링 프레임워크에서는 JUnit, Mockito, Spring Boot Test 등의 라이브러리를 사용

 

스프링 프레임 워크 리팩토링 라이브러리들 (JUnit, Mockito, Spring Boot Test)

EX

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public User createUser(User user) {
        return userRepository.save(user);
    }

    public User findUserById(Long id) {
        return userRepository.findById(id).orElse(null);
    }
}

 

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    private String email;

    // 생성자, getter, setter 생략
}

 

public interface UserRepository extends JpaRepository<User, Long> {
}

 

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {

    @Autowired
    private UserService userService;

    @MockBean
    private UserRepository userRepository;

    @Test
    public void testCreateUser() {
        User user = new User();
        user.setName("John Doe");
        user.setEmail("john.doe@example.com");

        when(userRepository.save(any(User.class))).thenReturn(user);

        User createdUser = userService.createUser(user);
        assertEquals(user.getName(), createdUser.getName());
        assertEquals(user.getEmail(), createdUser.getEmail());

        verify(userRepository, times(1)).save(user);
    }

    @Test
    public void testFindUserById() {
        User user = new User();
        user.setId(1L);
        user.setName("John Doe");
        user.setEmail("john.doe@example.com");

        when(userRepository.findById(1L)).thenReturn(Optional.of(user));

        User foundUser = userService.findUserById(1L);
        assertNotNull(foundUser);
        assertEquals(user.getId(), foundUser.getId());
        assertEquals(user.getName(), foundUser.getName());
        assertEquals(user.getEmail(), foundUser.getEmail());

        verify(userRepository, times(1)).findById(1L);
    }
}

 

 

위의 테스트 코드에서는 UserService의 createUser 및 findUserById 메서드를 테스트하고 있습니다. 

 

@RunWith(SpringRunner.class)와 @SpringBootTest 어노테이션을 사용하여 스프링 테스트 환경을 설정하고, @MockBean을 사용하여 UserRepository를 가짜로(Mock) 생성하여 의존성 주입을 진행합니다.

테스트 메서드에서는 Mockito의 when과 thenReturn을 사용하여 UserRepository의 메서드 호출 시 반환되는 값을 지정하고, assertEquals 및 assertNotNull을 사용하여 기대되는 결과를 검증합니다. 

 

마지막으로 verify를 사용하여 UserRepository의 메서드가 정확한 횟수만큼 호출되었는지 확인합니다.

728x90
반응형