[Spring Boot]단위테스트 vs 통합테스트

bbbbbhyun·2025년 2월 3일

Spring

목록 보기
10/12

spring boot에서 사용하는 테스트 종류에 대하여 공부한걸 정리해보자

단위 테스트

정의

개별 모듈(클래스, 메서드)을 독립적으로 테스트

특징

✅ 독립적 실행: 특정 클래스나 메서드만 테스트
✅ Mocking 사용: 외부 의존성을 제거하고 순수한 로직만 검증
✅ 빠른 속도: Spring Context를 로드하지 않기 때문에 빠름

장점

✔️ 실행 속도가 빠르다 (테스트 수행 시간이 짧음)
✔️ 특정 기능을 정확하게 검증할 수 있음
✔️ 문제가 발생했을 때 원인을 쉽게 찾을 수 있음
✔️ 개발 초기부터 작성 가능 (TDD 적용 가능)

단점

❌ 실제 환경과 다를 수 있음 (Mock 객체 사용)
❌ 여러 모듈이 결합된 기능 테스트는 어려움
❌ 데이터베이스, 네트워크 등과 연계된 기능 검증 불가

예시

@ExtendWith(MockitoExtension.class)
class MyServiceTest {

    @Mock
    private MyRepository myRepository;

    @InjectMocks
    private MyService myService;

    @Test
    void testFindById() {
        Long id = 1L;
        when(myRepository.findById(id)).thenReturn(Optional.of(new MyEntity(id, "Test")));

        MyEntity result = myService.findById(id);

        assertEquals("Test", result.getName());
    }
}

통합테스트

정의

여러 모듈(서비스, DB, API 등)을 통합하여 테스트

특징

✅ 여러 계층(Controller, Service, Repository 등) 테스트 가능
✅ Spring Context 로드 필요 → 실행 속도가 느림
✅ 실제 DB, API와 연계된 환경에서 테스트 가능

장점

✔️ 실제 환경과 유사한 조건에서 검증 가능
✔️ 모듈 간의 연결이 정상적으로 이루어지는지 확인 가능
✔️ 외부 시스템(API, DB 등)과의 연동 테스트 가능

단점

❌ 테스트 속도가 느림 (Spring Context를 로드해야 함)
❌ 특정 기능에서 문제가 발생하면 원인 파악이 어려울 수 있음
❌ 데이터베이스 연산이 포함되면 데이터 정리가 필요함 (@Transactional 사용)

예시

@SpringBootTest
@AutoConfigureMockMvc
class MyControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    @Transactional
    void logintest() throws Exception {
        //given
        HashMap<String, String> request = new HashMap<>();
        request.put("userId", "test111");
        request.put("pwd", "test123111");
        String content = new ObjectMapper().writeValueAsString(request);
        
        //when
        MvcResult result1 = mockMvc.perform(post("/user/login")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(content))
                .andExpect(status().isOk())
                .andReturn();
                
        //then
        Result result2 = new ObjectMapper().readValue(result1.getResponse().getContentAsString(), Result.class);
        assertThat(result2.getResult().getResultCode().equals("00")).isTrue();
        assertThat(result2.getResult().getResultMessage().equals("성공")).isTrue();
    }
}

비교

구분 단위 테스트 통합 테스트
대상 특정 클래스, 메서드, 컴포넌트 애플리케이션 전체 또는 일부 모듈의 연계
목적 특정 기능이 올바르게 동작하는지 검증 여러 컴포넌트 간의 협업이 정상적으로 이루어지는지 검증
환경 Mock 객체 사용, 실제 DB나 네트워크 미사용 실제 DB, API, 네트워크 환경과 상호작용
속도 빠름 (수ms ~ 수백ms) 느림 (수백ms ~ 수초)
의존성 독립적 실행 가능 여러 컴포넌트 간 의존성이 존재
어노테이션 @Test, @Mock, @InjectMocks @SpringBootTest, @Transactional, @AutoConfigureMockMvc

결론

단위 테스트를 사용해야 하는 경우

✔️ 특정 클래스나 메서드가 올바르게 동작하는지 확인할 때
✔️ 빠르게 실행 가능한 테스트가 필요할 때
✔️ 외부 의존성을 제거하고 로직만 검증할 때
✔️ TDD(Test Driven Development)를 적용할 때

통합 테스트를 사용해야 하는 경우

✔️ 여러 계층(Service, Repository, Controller 등)이 정상적으로 동작하는지 확인할 때
✔️ 실제 DB, API와 연동이 필요한 경우
✔️ 배포 전, 전체 애플리케이션이 정상 동작하는지 확인할 때
✔️ Spring Security, OAuth 등 인증/인가 기능을 테스트할 때

결론

  • 단위 테스트는 빠르고 독립적인 검증이 가능하지만, 실제 환경과 다를 수 있음
  • 통합 테스트는 실제 환경과 유사한 조건에서 실행되지만, 느리고 복잡할 수 있음
  • 두 가지를 조합해서 사용하는 것이 가장 좋음
profile
BackEnd developer

0개의 댓글