🧩 Spring Boot UnitTest란

정의

Spring Boot UnitTest는 실제 애플리케이션을 가능한 한 가볍게 띄워서 Controller, Service, Repository 동작을 검증하는 테스트 방식이다. 테스트 범위에 따라 @WebMvcTest@SpringBootTest를 나눠서 사용한다.

  • 컨트롤러 테스트는 빠르게 검증할 수 있다.
  • Repository 테스트는 실제 JPA 설정을 포함해 확인할 수 있다.
  • 테스트 범위를 나누면 속도와 정확도를 함께 챙길 수 있다.

⚙️ 단위테스트 환경 구성

먼저 단위테스트 환경을 구성하기 위해 Gradle 의존성을 추가한다.

testImplementation 'org.springframework.boot:spring-boot-starter-test'

의존성을 추가하면 Annotation 몇 개로 간단하게 테스트를 만들 수 있다. 아래는 테스트할 Controller 예시다.

@RestController  
@RequestMapping("/test")  
public class TestController {  

    @GetMapping("/string")  
    public String testString(){  
        return "test";  
    }  

    @GetMapping("/json")  
    public TestResponse getUserInfo(){  
        return new TestResponse("홍길동", "010-3333-3333");  
    }  

    @PostMapping("/json/withbody")  
    public TestResponse getEchoUserInfo(@RequestBody TestRequest request){  
        return new TestResponse(request.getName(), request.getRegistrationNumber());  
    }  
}

단위테스트 클래스는 IntelliJ의 Quick Fix 기능을 사용하면 적절한 경로에 자동으로 생성된다.

image

🧪 Controller 테스트

생성된 클래스에 사용할 중요한 애너테이션은 @WebMvcTest다.
MockMvc 환경을 구성해 Controller만 가볍게 테스트할 때 사용한다.

@WebMvcTest(TestController.class)  
class TestControllerTest {  

    @Autowired  
    private MockMvc mockMvc;  

    @Test  
    void testString() throws Exception{  
        mockMvc.perform(MockMvcRequestBuilders.get("/test/string"))  
                .andExpect(status().isOk())  
                .andExpect(content().string("test"));  
    }  

    @Test  
    void getUserInfo() throws Exception{  
        mockMvc.perform(MockMvcRequestBuilders.get("/test/json"))  
                .andExpect(status().isOk())  
                .andExpect(content().json("{\"name\":\"홍길동\",\"registrationNumber\":\"010-3333-3333\"}"));  
    }  

    @Test  
    void getEchoUserInfo() throws Exception {  
        String requestBody = "{\"name\":\"양사장\",\"registrationNumber\":\"010-8888-8888\"}";  

        mockMvc.perform(  
                MockMvcRequestBuilders.post("/test/json/withbody")  
                        .contentType(MediaType.APPLICATION_JSON)  
                        .content(requestBody)  
                )  
                .andExpect(status().isOk())  
                .andExpect(content().json(requestBody));  
    }  
}

MockMvc 인스턴스를 가져오면 Controller 테스트를 위와 같이 수행할 수 있다.

image

🧱 Repository 및 통합 테스트

Repository 테스트는 JPA 설정을 포함해야 하므로 전체 컨텍스트를 로드하는 @SpringBootTest를 사용한다. DB 연결, 보안 설정 등 실제 애플리케이션에서 사용하는 모든 빈과 설정이 테스트에 포함된다.

@SpringBootTest  
@Transactional
class UserRepositoryTest {  
    @Autowired  
    private UserRepository userRepository;  

    @Test  
    public void testSaveAndFindById() {  
        User user = new User("홍길동", "010-1111-1111");  
        User savedUser = userRepository.save(user);  
        User foundUser = userRepository.findById(savedUser.getId()).orElse(null);  

        assertThat(foundUser).isNotNull();  
        assertThat(foundUser.getName()).isEqualTo("홍길동");  
    }  
}

테스트를 하다 보면 Repository와 MockMvc를 한 클래스에서 사용해야 할 경우도 생긴다. 이때는 @SpringBootTest@AutoConfigureMockMvc를 함께 적용한다.

@SpringBootTest  
@AutoConfigureMockMvc  
@Transactional
class EdocControllerTest {
	@Autowired  
	private MockMvc mockMvc;
	//...
}

caution

DB에 영향을 줄 수 있는 테스트에는 @Transactional을 추가하는 것이 좋다.
@Transactional이 적용된 테스트는 종료 후 자동 롤백된다.

🧠 테스트 범위별 선택

테스트 방식 목적 특징
@WebMvcTest Controller 검증 빠르고 가볍다
@SpringBootTest 전체 흐름 검증 설정과 빈을 함께 확인한다
@SpringBootTest + @AutoConfigureMockMvc Controller와 Repository 혼합 검증 실제 환경에 가깝다

⚠️ 주의사항

  • @WebMvcTest는 Controller 중심 테스트에 적합하다.
  • @SpringBootTest는 무겁지만 실제 환경과 가장 가깝다.
  • JSON 응답 비교 시 ObjectMapper를 함께 쓰면 편하다.
  • DB를 건드리는 테스트는 롤백 전략을 꼭 고려해야 한다.

📌 정리

  • Spring Boot UnitTest는 테스트 범위를 나눠서 접근하는 것이 중요하다.
  • Controller는 @WebMvcTest, Repository는 @SpringBootTest를 주로 사용한다.
  • MockMvc, @Transactional, @AutoConfigureMockMvc 조합을 자주 활용한다.

연결문서

댓글남기기