이것저것
Mock 관련 Annotations
코딩공부
2025. 3. 3. 02:34
@Mock
- Mockito의 Mock 객체 생성
- 단순한 Mock 객체를 생성하지만, 의존성 주입은 자동으로 하지 않음
- 메서드 호출 시 기본적으로 null 또는 기본값을 반환
@Mock
private lateinit var emailService: EmailService // Mock 객체 생성
@Test
fun testEmailSending() {
`when`(emailService.sendEmail("test@example.com")).thenReturn("Success")
val result = emailService.sendEmail("test@example.com")
assertEquals("Success", result) // 반환값 검증
}
Mock 객체만 생성되고, UserService 등의 클래스에 자동 주입되지는 않음.
@InjectMocks
- Mock 객체를 주입하여 실제 객체 생성
- @Mock 또는 @Spy로 생성된 객체를 @InjectMocks가 달린 객체의 의존성으로 자동 주입
- 단위 테스트에서 의존성을 주입받는 실제 객체를 만들 때 사용
@Mock
private lateinit var emailService: EmailService
@InjectMocks
private lateinit var userService: UserService // emailService가 자동으로 주입됨
@Test
fun testRegisterUser() {
val user = User("test@example.com")
userService.registerUser(user)
verify(emailService, times(1)).sendEmail(user.email) // Mock 검증
}
emailService가 userService에 자동으로 주입됨
@MockBean (Spring Boot용)
- Spring Boot에서 @MockBean을 사용하면, 애플리케이션 컨텍스트에 등록된 빈을 대체
- @Mock과 달리 Spring ApplicationContext에 등록된 빈을 교체하기 때문에,
통합 테스트(@SpringBootTest)에서도 사용 가능 - 단위 테스트보다는 통합 테스트에서 특정 빈(Mock 객체)으로 교체할 때 유용
@SpringBootTest
class UserServiceTest {
@MockBean
private lateinit var emailService: EmailService // Spring 빈을 Mock으로 교체
@Autowired
private lateinit var userService: UserService // emailService가 주입됨
@Test
fun testRegisterUser() {
val user = User("test@example.com")
userService.registerUser(user)
verify(emailService, times(1)).sendEmail(user.email) // Mock 검증
}
}
Spring Context에서 emailService 빈을 대체하여 주입
@Spy
- 실제 객체를 생성하고 일부 메서드만 Mock 처리
- @Mock과 다르게 진짜 객체의 메서드를 호출할 수도 있음
- 특정 메서드만 when().thenReturn()으로 오버라이드 가능
@Spy
private lateinit var emailService: EmailService // 실제 객체 사용
@Test
fun testSpyEmailService() {
doReturn("Success").`when`(emailService).sendEmail("test@example.com")
val result = emailService.sendEmail("test@example.com")
assertEquals("Success", result) // Stub된 값 검증
verify(emailService, times(1)).sendEmail("test@example.com") // 호출 여부 확인
}
@Spy는 진짜 메서드를 호출할 수도 있고, 특정 메서드만 Mock 처리 가능
@ExtendWith(MockitoExtension::class) (JUnit 5용)
- JUnit 5에서 Mockito의 확장 기능을 활성화
- @Mock, @InjectMocks 등을 사용할 때 MockitoAnnotations.initMocks(this)가 필요 없이 자동으로 초기화
@ExtendWith(MockitoExtension::class)
class UserServiceTest {
@Mock
private lateinit var emailService: EmailService
@InjectMocks
private lateinit var userService: UserService
@Test
fun testRegisterUser() {
val user = User("test@example.com")
userService.registerUser(user)
verify(emailService, times(1)).sendEmail(user.email)
}
}
@ExtendWith(MockitoExtension::class)를 사용하면 Mockito 객체를 자동 초기화
@Spy
@Mock과 호출하는 방법이 다름
@Mock vs @Spy 호출 방법 차이
구분 | @Mock | @Spy |
객체 타입 | 가짜(Mock) 객체 | 실제 객체 |
메서드 기본 동작 | 기본적으로 null, 빈 값 반환 | 실제 메서드 실행 |
Stub 처리 방식 | when().thenReturn() 사용 | doReturn().when() 사용 |
실제 메서드 실행 여부 | ❌ 실행되지 않음 | ✅ 실행됨 |
사용 목적 | 테스트 대상의 완전한 대체 | 일부만 Mock, 나머지는 원래 동작 |
when().thenReturn() vs doReturn().when() 차이
호출 방식 | when().thenReturn() | doReturn().when() |
사용 가능 대상 | @Mock | @Spy |
실제 메서드 실행 여부 | ❌ 실행 안 됨 | ✅ 원래 메서드 실행 가능 |
Exception 발생 가능성 | @Spy에서 사용하면 실제 메서드가 실행되어 NullPointerException 발생 가능 |
안전하게 Stub 가능 |