코드의 가장 작은 기능적 단위를 테스트하는 프로세스로, 메서드를 테스트하기 위한 또다른 메서드다.
=> 결론!
장기적으로 볼 때 더 빠르고 안정적인 개발이 가능하게됨

JUnit이란?
@Autowired는 스프링 프레임워크에서 사용되는 어노테이션으로, 스프링 컨테이너가 관리하는 빈(Bean) 중에서 필요한 객체의 타입과 일치하는 객체를 찾아 자동으로 주입(DI)해주는 역할을 해준다
즉, 개발자가 직접 객체를 생성하고 연결할 필요 없이, Autowired가 붙은 변수나 생성자에 자동으로 객체를 연결해 줌으로써 코드 작성을 간소화하고 의존성을 관리할 수 있게 하는데,
이는 테스트에서 주입하는 데에 도움을 준다.
우리가 직접 테스트를 해보려면
TestService testService = new TestService(new TestRepository());
이런식으로 반복을 해주어야하는데,
이에 대하여 귀찮으니까 생긴 것을 Autowired라고 생각해주면 된다
그래서 간단하게 독립적인 것들 작성할 때에는
@Autowired를 통해 작성해주면 끝!
@Autowired
private TestService testService;
이러면 TestService 안에 있는 TestRepository 등 다양한 의존성에 대하여 알아서 주입을 해준다.
하지만 작업을 하다보면 의존성 주입이 굉장히 잦아지고
테스트의 반복작업도 어려워지게 된다.
모두가 다 연결되어 동작하다보면 서비스 하나에 대해서만 테스트하려는 것이 힘들어질 수 있다.
가령 User 클래스가 데이터베이스나 외부 API와 같은 복잡한 시스템에 의존하고 있다면, User와 관련된 다른 클래스를 테스트하기 위해 User.class 환경을 통째로 구축해야 하는 어려움이 있다.
이러한 문제를 해결하기 위해 가짜 객체(Mock Object)를 수동으로 만들기도 했는데, 이는 코드의 양을 늘리고 유지보수를 어렵게 만드는 반복적인 작업(boilerplate)으로 생겨난 것이 Mockito 이다!
-> 가짜(Mock)을 만들어서 내가 원하는 방식으로 동작하게 하자!
= Mockito 라이브러리를 활용
예시를 통해 확인해보자
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
}
UserRepository에 대하여 가짜 객체인 Mock을 생성하고, userService에 대하여 가짜로 생성한 Mock을 주입할 수 있도록 설계한다
이 때, Mock은 실제 동작이 아닌 가짜 객체이므로, 실제 userRepository를 사용하는 것이 아니므로 인메모리 객체 생성으로 작업을 해주는 것이 좋다.
Mockito 기반 테스트는 일반적으로 given → when → then 구조를 따른다.
예제를 확인해보자
@Test
void 로그인_테스트() {
// given
User user = new User("test", 20, "test@test.com");
// when
when(userService.createAccount()).returnThen(user);
// then
assertThat()....
}
@Mock, @InjectMocks)@WebMvcTest, @DataJpaTest) + 필요 시 @MockBean@SpringBootTest + 실제 빈 @Autowired (필요하면 일부 의존성만 @MockBean)공통: JUnit5는 @ExtendWith(SpringExtension.class)가 암묵 포함(슬라이스/부트 테스트 사용 시).
단위 테스트(순수 Mockito): @ExtendWith(MockitoExtension.class) 또는 MockitoAnnotations.openMocks(this)
슬라이스/통합: @WebMvcTest, @DataJpaTest, @SpringBootTest
Mock 주입 위치
@Mock + @InjectMocks@MockBean(빈을 대체), @SpyBean(부분 모킹)목표: 서비스 메서드의 분기/계산/예외 처리만 보기
선택: Mockito 단독 (스프링 컨텍스트 없음)
class OrderServiceTest {
@InjectMocks OrderService service;
@Mock OrderRepository repo;
@BeforeEach void init(){ MockitoAnnotations.openMocks(this); }
@Test void 할인적용() {
when(repo.findById(1L)).thenReturn(Optional.of(order(...)));
var price = service.calculatePrice(1L);
assertEquals(9000, price);
}
}
목표: 엔티티 매핑, 쿼리 메서드, 영속성 컨텍스트 동작
선택: @DataJpaTest (내장 DB/H2 + 스캔 최소화)
@WebMvcTest + @MockBean@DataJpaTest@SpringBootTest (+ 필요 시 일부만 @MockBean)@WebMvcTest + MockMvc + 전역 예외/밸리데이션 검증@DataJpaTest + Testcontainers(MySQL/Postgres)@SpringBootTest(webEnvironment = RANDOM_PORT) + RestAssured/MockMvc다음 글에서는 통합 테스트와 WebMvcTest에 대하여 심화적으로 가져와보겠다!