@Mock 과 @InjectedMock
@Mock과 @InjectMocks의 차이를 알아볼게요. 이 둘은 함께 자주 쓰이지만 서로 다른 역할을 해요.
🔹 @Mock
- Mockito에서 제공
- Mock 객체를 생성해줌
- 단독으로는 그냥 가짜 객체일 뿐, 아무 데도 주입되지 않음
@Mock
private MyRepository myRepository; // 가짜 객체 생성
🔸 @InjectMocks
- 역시 Mockito에서 제공
- 테스트 대상 객체(테스트할 클래스)를 생성하고,
그 안에 있는 의존성 필드에@Mock으로 만든 객체들을 자동으로 주입
@InjectMocks
private MyService myService; // MyService 객체를 만들고, 내부에 있는 MyRepository 등에 @Mock 객체를 주입
✅ 간단 예시
@ExtendWith(MockitoExtension.class)
class MyServiceTest {
@Mock
private MyRepository myRepository;
@InjectMocks
private MyService myService;
@Test
void testSomething() {
// myService는 실제 객체
// myRepository는 mock 객체
// myService 내부에서 myRepository가 사용될 때 mock이 주입됨
}
}
📌 정리하자면:
| 어노테이션 | 역할 |
|---|---|
@Mock |
가짜(Mock) 객체 생성 |
@InjectMocks |
테스트 대상 객체를 생성하고, @Mock 객체를 그 안에 주입 |
즉, @Mock이 가짜 부품을 만드는 거고,
@InjectMocks는 그 부품을 조립해서 테스트 대상 객체를 만드는 거예요.
@MockBean 과 @InjectMock 혼용할 수 있을까요?
@MockBean과 @InjectMocks의 혼용… 가능은 하지만, 거의 안 하고, 대부분은 피하는 게 좋아요.
왜냐면 이 둘은 역할이 완전히 다르고, 쓰는 테스트 환경이 충돌할 수 있기 때문이에요.
📌 핵심 정리
| 어노테이션 | 역할 | 주로 쓰는 테스트 환경 |
|---|---|---|
@MockBean |
Spring 컨텍스트에 있는 Bean을 Mock으로 교체 | @SpringBootTest, @WebMvcTest 등 |
@InjectMocks |
테스트 대상 객체를 만들고, @Mock된 의존성을 직접 주입 |
@ExtendWith(MockitoExtension.class) |
🚫 왜 혼용이 거의 없을까?
@MockBean은 Spring이 관리하는 Bean이고,
@InjectMocks는 Mockito가 관리하는 객체에 Mock을 주입하는 방식이거든요.- Spring vs Mockito → 둘 다 주입하려고 하면 어떤 게 실제로 주입되는지 예측이 어렵고 충돌 가능성 있음
📎 예외적으로 가능은 한 경우 (하지만 추천은 안 함)
예를 들어, 다음과 같이 Spring Boot 컨텍스트를 띄우고 @MockBean으로 외부 Bean을 막으면서도,
@InjectMocks를 써서 특정 빈이 아닌 클래스를 테스트 대상으로 쓸 수는 있어요:
@SpringBootTest
class MyServiceTest {
@MockBean
private ExternalService externalService; // 이건 Spring 컨텍스트에 등록된 Bean 대체
@Mock
private InternalRepository internalRepository; // 순수 Mockito mock
@InjectMocks
private MyService myService; // internalRepository는 여기에 직접 주입
@Test
void testSomething() {
// 가능한 구조지만 복잡하고 혼란스럽기 쉬움
}
}
✔️ 되긴 하지만… 이럴 바엔 차라리 완전한 통합 테스트 or 완전한 단위 테스트 중 하나로 가는 게 깔끔합니다.
✅ 실전 팁
- 단위 테스트(Unit Test):
@Mock+@InjectMocks - Spring 통합 테스트:
@MockBean+@Autowired로 테스트 대상 주입